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