blob: cac43ec4bc18d75f761af5ca560343890c5686da [file] [log] [blame]
Patrick Williams975a06f2022-10-21 14:42:47 -05001From 0df82487a7a253c601ca20ca1bd64fbb9ed64230 Mon Sep 17 00:00:00 2001
2From: Vishnu Banavath <vishnu.banavath@arm.com>
3Date: Fri, 3 Dec 2021 19:19:24 +0000
4Subject: [PATCH 06/19] Add secure storage ipc backend
5
6Add secure storage ipc ff-m implementation which may use
7openamp as rpc to communicate with other processor.
8
9Upstream-Status: Pending
10Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
11Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
12---
13 .../service/common/psa_ipc/service_psa_ipc.c | 143 +++++++++++-
14 .../secure_storage_ipc/component.cmake | 14 ++
15 .../secure_storage_ipc/secure_storage_ipc.c | 214 ++++++++++++++++++
16 .../secure_storage_ipc/secure_storage_ipc.h | 52 +++++
17 deployments/se-proxy/se-proxy.cmake | 1 +
18 5 files changed, 420 insertions(+), 4 deletions(-)
19 create mode 100644 components/service/secure_storage/backend/secure_storage_ipc/component.cmake
20 create mode 100644 components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
21 create mode 100644 components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
22
23diff --git a/components/service/common/psa_ipc/service_psa_ipc.c b/components/service/common/psa_ipc/service_psa_ipc.c
24index e8093c20a523..95a07c135f31 100644
25--- a/components/service/common/psa_ipc/service_psa_ipc.c
26+++ b/components/service/common/psa_ipc/service_psa_ipc.c
27@@ -16,6 +16,52 @@
28 #include <psa/client.h>
29 #include "service_psa_ipc_openamp_lib.h"
30
31+static struct psa_invec *psa_call_in_vec_param(uint8_t *req)
32+{
33+ return (struct psa_invec *)(req + sizeof(struct ns_openamp_msg));
34+}
35+
36+static struct psa_outvec *psa_call_out_vec_param(uint8_t *req, size_t in_len)
37+{
38+ return (struct psa_outvec *)(req + sizeof(struct ns_openamp_msg) +
39+ (in_len * sizeof(struct psa_invec)));
40+}
41+
42+static size_t psa_call_header_len(const struct psa_invec *in_vec, size_t in_len,
43+ struct psa_outvec *out_vec, size_t out_len)
44+{
45+ return sizeof(struct ns_openamp_msg) + (in_len * sizeof(*in_vec)) +
46+ (out_len * sizeof(*out_vec));
47+}
48+
49+static size_t psa_call_in_vec_len(const struct psa_invec *in_vec, size_t in_len)
50+{
51+ size_t req_len = 0;
52+ int i;
53+
54+ if (!in_vec || !in_len)
55+ return 0;
56+
57+ for (i = 0; i < in_len; i++)
58+ req_len += in_vec[i].len;
59+
60+ return req_len;
61+}
62+
63+static size_t psa_call_out_vec_len(const struct psa_outvec *out_vec, size_t out_len)
64+{
65+ size_t resp_len = 0;
66+ int i;
67+
68+ if (!out_vec || !out_len)
69+ return 0;
70+
71+ for (i = 0; i < out_len; i++)
72+ resp_len += out_vec[i].len;
73+
74+ return resp_len;
75+}
76+
77 psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
78 uint32_t version)
79 {
80@@ -31,7 +77,7 @@ psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
81 rpc_handle = rpc_caller_begin(caller, &req,
82 sizeof(struct ns_openamp_msg));
83 if (!rpc_handle) {
84- EMSG("psa_connect: could not get handle");
85+ EMSG("psa_connect: could not get rpc handle");
86 return PSA_ERROR_GENERIC_ERROR;
87 }
88
89@@ -56,14 +102,100 @@ psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
90 return resp_msg ? (psa_handle_t)resp_msg->reply : PSA_NULL_HANDLE;
91 }
92
93-psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t handle,
94+psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
95 int32_t type, const struct psa_invec *in_vec,
96 size_t in_len, struct psa_outvec *out_vec, size_t out_len)
97 {
98+ psa_status_t psa_status = PSA_SUCCESS;
99+ struct s_openamp_msg *resp_msg = NULL;
100+ struct psa_outvec *out_vec_param;
101+ struct psa_invec *in_vec_param;
102+ struct ns_openamp_msg *req_msg;
103+ rpc_call_handle rpc_handle;
104+ size_t out_vec_len;
105+ size_t in_vec_len;
106+ size_t header_len;
107+ uint8_t *payload;
108+ size_t resp_len;
109+ uint8_t *resp;
110+ uint8_t *req;
111+ int ret;
112+ int i;
113+
114+ if ((psa_handle == PSA_NULL_HANDLE) || !caller)
115+ return PSA_ERROR_INVALID_ARGUMENT;
116+
117+ header_len = psa_call_header_len(in_vec, in_len, out_vec, out_len);
118+ in_vec_len = psa_call_in_vec_len(in_vec, in_len);
119+ out_vec_len = psa_call_out_vec_len(out_vec, out_len);
120
121+ rpc_handle = rpc_caller_begin(caller, &req, header_len + in_vec_len);
122+ if (!rpc_handle) {
123+ EMSG("psa_call: could not get handle");
124+ return PSA_ERROR_GENERIC_ERROR;
125+ }
126+
127+ payload = req + header_len;
128+
129+ out_vec_param = psa_call_out_vec_param(req, in_len);
130+ in_vec_param = psa_call_in_vec_param(req);
131+
132+ req_msg = (struct ns_openamp_msg *)req;
133+
134+ req_msg->call_type = OPENAMP_PSA_CALL;
135+ req_msg->request_id = 1234;
136+ req_msg->params.psa_call_params.handle = psa_handle;
137+ req_msg->params.psa_call_params.type = type;
138+ req_msg->params.psa_call_params.in_len = in_len;
139+ req_msg->params.psa_call_params.in_vec = rpc_caller_virt_to_phys(caller, in_vec_param);
140+ req_msg->params.psa_call_params.out_len = out_len;
141+ req_msg->params.psa_call_params.out_vec = rpc_caller_virt_to_phys(caller, out_vec_param);
142+
143+ for (i = 0; i < in_len; i++) {
144+ in_vec_param[i].base = rpc_caller_virt_to_phys(caller, payload);
145+ in_vec_param[i].len = in_vec[i].len;
146+
147+ memcpy(payload, in_vec[i].base, in_vec[i].len);
148+ payload += in_vec[i].len;
149+ }
150+
151+ for (i = 0; i < out_len; i++) {
152+ out_vec_param[i].base = NULL;
153+ out_vec_param[i].len = out_vec[i].len;
154+ }
155+
156+ ret = rpc_caller_invoke(caller, rpc_handle, 0, &psa_status, &resp,
157+ &resp_len);
158+ if (ret != TS_RPC_CALL_ACCEPTED) {
159+ EMSG("psa_call: invoke failed: %d", ret);
160+ return PSA_ERROR_GENERIC_ERROR;
161+ }
162+
163+ if (psa_status != PSA_SUCCESS) {
164+ EMSG("psa_call: psa_status invoke failed: %d", psa_status);
165+ return PSA_ERROR_GENERIC_ERROR;
166+ }
167+
168+ resp_msg = (struct s_openamp_msg *)resp;
169+
170+ if (!resp_msg || !out_len || resp_msg->reply != PSA_SUCCESS)
171+ goto caller_end;
172+
173+ out_vec_param = (struct psa_outvec *)rpc_caller_phys_to_virt(caller,
174+ resp_msg->params.out_vec);
175+
176+ for (i = 0; i < resp_msg->params.out_len; i++) {
177+ memcpy(out_vec[i].base, rpc_caller_phys_to_virt(caller, out_vec_param[i].base),
178+ out_vec[i].len);
179+ }
180+
181+caller_end:
182+ rpc_caller_end(caller, rpc_handle);
183+
184+ return resp_msg ? resp_msg->reply : PSA_ERROR_COMMUNICATION_FAILURE;
185 }
186
187-void psa_close(struct rpc_caller *caller, psa_handle_t handle)
188+void psa_close(struct rpc_caller *caller, psa_handle_t psa_handle)
189 {
190 psa_status_t psa_status = PSA_SUCCESS;
191 struct s_openamp_msg *resp_msg = NULL;
192@@ -74,6 +206,9 @@ void psa_close(struct rpc_caller *caller, psa_handle_t handle)
193 uint8_t *req;
194 int ret;
195
196+ if ((psa_handle == PSA_NULL_HANDLE) || !caller)
197+ return;
198+
199 rpc_handle = rpc_caller_begin(caller, &req,
200 sizeof(struct ns_openamp_msg));
201 if (!rpc_handle) {
202@@ -84,7 +219,7 @@ void psa_close(struct rpc_caller *caller, psa_handle_t handle)
203 req_msg = (struct ns_openamp_msg *)req;
204
205 req_msg->call_type = OPENAMP_PSA_CLOSE;
206- req_msg->params.psa_close_params.handle = handle;
207+ req_msg->params.psa_close_params.handle = psa_handle;
208
209 ret = rpc_caller_invoke(caller, rpc_handle, 0, &psa_status, &resp,
210 &resp_len);
211diff --git a/components/service/secure_storage/backend/secure_storage_ipc/component.cmake b/components/service/secure_storage/backend/secure_storage_ipc/component.cmake
212new file mode 100644
213index 000000000000..5d8f6714e0bd
214--- /dev/null
215+++ b/components/service/secure_storage/backend/secure_storage_ipc/component.cmake
216@@ -0,0 +1,14 @@
217+#-------------------------------------------------------------------------------
218+# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
219+#
220+# SPDX-License-Identifier: BSD-3-Clause
221+#
222+#-------------------------------------------------------------------------------
223+if (NOT DEFINED TGT)
224+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
225+endif()
226+
227+target_sources(${TGT} PRIVATE
228+ "${CMAKE_CURRENT_LIST_DIR}/secure_storage_ipc.c"
229+ )
230+
231diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
232new file mode 100644
233index 000000000000..9b55f77dd395
234--- /dev/null
235+++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
236@@ -0,0 +1,214 @@
237+/*
238+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
239+ *
240+ * SPDX-License-Identifier: BSD-3-Clause
241+ */
242+
243+#include <protocols/rpc/common/packed-c/status.h>
244+#include "secure_storage_ipc.h"
245+#include <psa/client.h>
246+#include <psa/sid.h>
247+#include <rpc_caller.h>
248+#include <string.h>
249+#include <trace.h>
250+
251+
252+static psa_status_t secure_storage_ipc_set(void *context, uint32_t client_id,
253+ psa_storage_uid_t uid, size_t data_length,
254+ const void *p_data, psa_storage_create_flags_t create_flags)
255+{
256+ struct secure_storage_ipc *ipc = context;
257+ struct rpc_caller *caller = ipc->client.caller;
258+ psa_handle_t psa_handle;
259+ psa_status_t psa_status;
260+ struct psa_invec in_vec[] = {
261+ { .base = &uid, .len = sizeof(uid) },
262+ { .base = p_data, .len = data_length },
263+ { .base = &create_flags, .len = sizeof(create_flags) },
264+ };
265+
266+ (void)client_id;
267+
268+ ipc->client.rpc_status = TS_RPC_CALL_ACCEPTED;
269+
270+ /* Validating input parameters */
271+ if (p_data == NULL)
272+ return PSA_ERROR_INVALID_ARGUMENT;
273+
274+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
275+ TFM_PS_SET, in_vec, IOVEC_LEN(in_vec), NULL, 0);
276+ if (psa_status < 0)
277+ EMSG("ipc_set: psa_call failed: %d", psa_status);
278+
279+ return psa_status;
280+}
281+
282+static psa_status_t secure_storage_ipc_get(void *context,
283+ uint32_t client_id,
284+ psa_storage_uid_t uid,
285+ size_t data_offset,
286+ size_t data_size,
287+ void *p_data,
288+ size_t *p_data_length)
289+{
290+ struct secure_storage_ipc *ipc = context;
291+ struct rpc_caller *caller = ipc->client.caller;
292+ psa_handle_t psa_handle;
293+ psa_status_t psa_status;
294+ uint32_t offset = (uint32_t)data_offset;
295+ struct psa_invec in_vec[] = {
296+ { .base = &uid, .len = sizeof(uid) },
297+ { .base = &offset, .len = sizeof(offset) },
298+ };
299+ struct psa_outvec out_vec[] = {
300+ { .base = p_data, .len = data_size },
301+ };
302+
303+ if (!p_data_length) {
304+ EMSG("ipc_get: p_data_length not defined");
305+ return PSA_ERROR_INVALID_ARGUMENT;
306+ }
307+
308+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
309+ TFM_PS_GET, in_vec, IOVEC_LEN(in_vec),
310+ out_vec, IOVEC_LEN(out_vec));
311+ if (psa_status == PSA_SUCCESS)
312+ *p_data_length = out_vec[0].len;
313+
314+ return psa_status;
315+}
316+
317+static psa_status_t secure_storage_ipc_get_info(void *context,
318+ uint32_t client_id,
319+ psa_storage_uid_t uid,
320+ struct psa_storage_info_t *p_info)
321+{
322+ struct secure_storage_ipc *ipc = context;
323+ struct rpc_caller *caller = ipc->client.caller;
324+ psa_handle_t psa_handle;
325+ psa_status_t psa_status;
326+ struct psa_invec in_vec[] = {
327+ { .base = &uid, .len = sizeof(uid) },
328+ };
329+ struct psa_outvec out_vec[] = {
330+ { .base = p_info, .len = sizeof(*p_info) },
331+ };
332+
333+ (void)client_id;
334+
335+ /* Validating input parameters */
336+ if (!p_info)
337+ return PSA_ERROR_INVALID_ARGUMENT;
338+
339+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
340+ TFM_PS_GET_INFO, in_vec,
341+ IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
342+ if (psa_status != PSA_SUCCESS)
343+ EMSG("ipc_get_info: failed to psa_call: %d", psa_status);
344+
345+ return psa_status;
346+}
347+
348+static psa_status_t secure_storage_ipc_remove(void *context,
349+ uint32_t client_id,
350+ psa_storage_uid_t uid)
351+{
352+ struct secure_storage_ipc *ipc = context;
353+ struct rpc_caller *caller = ipc->client.caller;
354+ psa_handle_t psa_handle;
355+ psa_status_t psa_status;
356+ struct psa_invec in_vec[] = {
357+ { .base = &uid, .len = sizeof(uid) },
358+ };
359+
360+ (void)client_id;
361+
362+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
363+ TFM_PS_REMOVE, in_vec,
364+ IOVEC_LEN(in_vec), NULL, 0);
365+ if (psa_status != PSA_SUCCESS)
366+ EMSG("ipc_remove: failed to psa_call: %d", psa_status);
367+
368+ return psa_status;
369+}
370+
371+static psa_status_t secure_storage_ipc_create(void *context,
372+ uint32_t client_id,
373+ uint64_t uid,
374+ size_t capacity,
375+ uint32_t create_flags)
376+{
377+ (void)context;
378+ (void)uid;
379+ (void)client_id;
380+ (void)capacity;
381+ (void)create_flags;
382+
383+ return PSA_ERROR_NOT_SUPPORTED;
384+}
385+
386+static psa_status_t secure_storage_set_extended(void *context,
387+ uint32_t client_id,
388+ uint64_t uid,
389+ size_t data_offset,
390+ size_t data_length,
391+ const void *p_data)
392+{
393+ (void)context;
394+ (void)uid;
395+ (void)client_id;
396+ (void)data_offset;
397+ (void)data_length;
398+ (void)p_data;
399+
400+ return PSA_ERROR_NOT_SUPPORTED;
401+}
402+
403+static uint32_t secure_storage_get_support(void *context, uint32_t client_id)
404+{
405+ struct secure_storage_ipc *ipc = context;
406+ struct rpc_caller *caller = ipc->client.caller;
407+ psa_handle_t psa_handle;
408+ psa_status_t psa_status;
409+ uint32_t support_flags;
410+ struct psa_outvec out_vec[] = {
411+ { .base = &support_flags, .len = sizeof(support_flags) },
412+ };
413+
414+ (void)client_id;
415+
416+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
417+ TFM_PS_GET_SUPPORT, NULL, 0,
418+ out_vec, IOVEC_LEN(out_vec));
419+ if (psa_status != PSA_SUCCESS)
420+ EMSG("ipc_get_support: failed to psa_call: %d", psa_status);
421+
422+ return psa_status;
423+}
424+
425+struct storage_backend *secure_storage_ipc_init(struct secure_storage_ipc *context,
426+ struct rpc_caller *caller)
427+{
428+ service_client_init(&context->client, caller);
429+
430+ static const struct storage_backend_interface interface =
431+ {
432+ .set = secure_storage_ipc_set,
433+ .get = secure_storage_ipc_get,
434+ .get_info = secure_storage_ipc_get_info,
435+ .remove = secure_storage_ipc_remove,
436+ .create = secure_storage_ipc_create,
437+ .set_extended = secure_storage_set_extended,
438+ .get_support = secure_storage_get_support,
439+ };
440+
441+ context->backend.context = context;
442+ context->backend.interface = &interface;
443+
444+ return &context->backend;
445+}
446+
447+void secure_storage_ipc_deinit(struct secure_storage_ipc *context)
448+{
449+ service_client_deinit(&context->client);
450+}
451diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
452new file mode 100644
453index 000000000000..e8c1e8fd2f92
454--- /dev/null
455+++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
456@@ -0,0 +1,52 @@
457+/*
458+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
459+ *
460+ * SPDX-License-Identifier: BSD-3-Clause
461+ */
462+
463+#ifndef SECURE_STORAGE_IPC_H
464+#define SECURE_STORAGE_IPC_H
465+
466+#include <service/secure_storage/backend/storage_backend.h>
467+#include <service/common/client/service_client.h>
468+
469+#ifdef __cplusplus
470+extern "C" {
471+#endif
472+
473+/**
474+ * @brief Secure storage ipc instance
475+ */
476+struct secure_storage_ipc
477+{
478+ struct storage_backend backend;
479+ struct service_client client;
480+};
481+
482+/**
483+ * @brief Initialize a secure storage ipc client
484+ *
485+ * A secure storage client is a storage backend that makes RPC calls
486+ * to a remote secure storage provider.
487+ *
488+ * @param[in] context Instance data
489+ * @param[in] rpc_caller RPC caller instance
490+ *
491+ *
492+ * @return Pointer to inialized storage backend or NULL on failure
493+ */
494+struct storage_backend *secure_storage_ipc_init(struct secure_storage_ipc *context,
495+ struct rpc_caller *caller);
496+
497+/**
498+ * @brief Deinitialize a secure storage ipc client
499+ *
500+ * @param[in] context Instance data
501+ */
502+void secure_storage_ipc_deinit(struct secure_storage_ipc *context);
503+
504+#ifdef __cplusplus
505+}
506+#endif
507+
508+#endif /* SECURE_STORAGE_IPC_H */
509diff --git a/deployments/se-proxy/se-proxy.cmake b/deployments/se-proxy/se-proxy.cmake
510index dd0c5d00c21e..cd51460406ca 100644
511--- a/deployments/se-proxy/se-proxy.cmake
512+++ b/deployments/se-proxy/se-proxy.cmake
513@@ -45,6 +45,7 @@ add_components(TARGET "se-proxy"
514 "components/service/crypto/factory/full"
515 "components/service/secure_storage/include"
516 "components/service/secure_storage/frontend/secure_storage_provider"
517+ "components/service/secure_storage/backend/secure_storage_ipc"
518 "components/service/attestation/include"
519 "components/service/attestation/provider"
520 "components/service/attestation/provider/serializer/packed-c"
521--
5222.38.0
523