ITS: Implement the top layer of the ITS service

Implements the secure and non-secure top layer of the ITS service,
including a new manifest file, and generates the required veneers.
Updates the partition manifest with added SIDs. It also adds the
necessary CMake files to build the ITS service.

Change-Id: I6d66b01de56145d24a0bcbf0597ca158b6da3386
Signed-off-by: Tudor Cretu <tudor.cretu@arm.com>
diff --git a/interface/include/psa_manifest/sid.h b/interface/include/psa_manifest/sid.h
index 49169ee..ac7ccf7 100644
--- a/interface/include/psa_manifest/sid.h
+++ b/interface/include/psa_manifest/sid.h
@@ -26,6 +26,16 @@
 #define TFM_SST_GET_SUPPORT_SID                                    (0x00000064U)
 #define TFM_SST_GET_SUPPORT_VERSION                                (1U)
 
+/******** TFM_SP_ITS ********/
+#define TFM_ITS_SET_SID                                            (0x00000070U)
+#define TFM_ITS_SET_VERSION                                        (1U)
+#define TFM_ITS_GET_SID                                            (0x00000071U)
+#define TFM_ITS_GET_VERSION                                        (1U)
+#define TFM_ITS_GET_INFO_SID                                       (0x00000072U)
+#define TFM_ITS_GET_INFO_VERSION                                   (1U)
+#define TFM_ITS_REMOVE_SID                                         (0x00000073U)
+#define TFM_ITS_REMOVE_VERSION                                     (1U)
+
 /******** TFM_SP_CRYPTO ********/
 #define TFM_CRYPTO_SID                                             (0x00000080U)
 #define TFM_CRYPTO_VERSION                                         (1U)
diff --git a/interface/include/tfm_its_defs.h b/interface/include/tfm_its_defs.h
new file mode 100644
index 0000000..852f8f4
--- /dev/null
+++ b/interface/include/tfm_its_defs.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_ITS_DEFS_H__
+#define __TFM_ITS_DEFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Invalid UID */
+#define TFM_ITS_INVALID_UID 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_ITS_DEFS_H__ */
diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h
index 0a24f47..23b4f8d 100644
--- a/interface/include/tfm_veneers.h
+++ b/interface/include/tfm_veneers.h
@@ -23,6 +23,12 @@
 psa_status_t tfm_tfm_sst_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 psa_status_t tfm_tfm_sst_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 
+/******** TFM_SP_ITS ********/
+psa_status_t tfm_tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 /******** TFM_SP_AUDIT_LOG ********/
 psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
diff --git a/interface/src/tfm_its_func_api.c b/interface/src/tfm_its_func_api.c
new file mode 100644
index 0000000..483cbee
--- /dev/null
+++ b/interface/src/tfm_its_func_api.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/internal_trusted_storage.h"
+#include "tfm_api.h"
+
+#include "tfm_ns_interface.h"
+#include "tfm_veneers.h"
+
+#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
+
+psa_status_t psa_its_set(psa_storage_uid_t uid,
+                         size_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags)
+{
+    psa_status_t status;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = p_data, .len = data_length },
+        { .base = &create_flags, .len = sizeof(create_flags) }
+    };
+
+    status = tfm_ns_interface_dispatch((veneer_fn)tfm_tfm_its_set_req_veneer,
+                                       (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                       (uint32_t)NULL, 0);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_get(psa_storage_uid_t uid,
+                         size_t data_offset,
+                         size_t data_size,
+                         void *p_data,
+                         size_t *p_data_length)
+{
+    psa_status_t status;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = &data_offset, .len = sizeof(data_offset) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_data, .len = data_size }
+    };
+
+    if (p_data_length == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = tfm_ns_interface_dispatch((veneer_fn)tfm_tfm_its_get_req_veneer,
+                                       (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                       (uint32_t)out_vec, IOVEC_LEN(out_vec));
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *p_data_length = out_vec[0].len;
+
+    return status;
+}
+
+psa_status_t psa_its_get_info(psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info)
+{
+    psa_status_t status;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_info, .len = sizeof(*p_info) }
+    };
+
+    status = tfm_ns_interface_dispatch(
+                                     (veneer_fn)tfm_tfm_its_get_info_req_veneer,
+                                     (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                     (uint32_t)out_vec, IOVEC_LEN(out_vec));
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_remove(psa_storage_uid_t uid)
+{
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    return tfm_ns_interface_dispatch((veneer_fn)tfm_tfm_its_remove_req_veneer,
+                                     (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                     (uint32_t)NULL, 0);
+}
diff --git a/interface/src/tfm_its_ipc_api.c b/interface/src/tfm_its_ipc_api.c
new file mode 100644
index 0000000..9326f7b
--- /dev/null
+++ b/interface/src/tfm_its_ipc_api.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/internal_trusted_storage.h"
+#include "tfm_api.h"
+
+#include "psa/client.h"
+#include "psa_manifest/sid.h"
+
+#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
+
+psa_status_t psa_its_set(psa_storage_uid_t uid,
+                         size_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = p_data, .len = data_length },
+        { .base = &create_flags, .len = sizeof(create_flags) }
+    };
+
+    handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_get(psa_storage_uid_t uid,
+                         size_t data_offset,
+                         size_t data_size,
+                         void *p_data,
+                         size_t *p_data_length)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = &data_offset, .len = sizeof(data_offset) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_data, .len = data_size }
+    };
+
+    if (p_data_length == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *p_data_length = out_vec[0].len;
+
+    return status;
+}
+
+psa_status_t psa_its_get_info(psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_info, .len = sizeof(*p_info) }
+    };
+
+    handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_remove(psa_storage_uid_t uid)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+
+    psa_close(handle);
+
+    return status;
+}