1 /*
2 * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
3 * Copyright (c) 2022-2023 Cypress Semiconductor Corporation (an Infineon
4 * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5 * reserved.
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11 #include "critical_section.h"
12 #include "ffm/backend.h"
13 #include "ffm/psa_api.h"
14 #include "load/service_defs.h"
15 #include "spm.h"
16
17 /* PSA APIs only needed by connection-based services */
18
tfm_spm_client_psa_connect(uint32_t sid,uint32_t version)19 psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
20 {
21 struct service_t *service;
22 struct connection_t *p_connection;
23 int32_t client_id;
24 psa_handle_t handle;
25 bool ns_caller = tfm_spm_is_ns_caller();
26 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
27
28 /*
29 * It is a PROGRAMMER ERROR if the RoT Service does not exist on the
30 * platform.
31 */
32 service = tfm_spm_get_service_by_sid(sid);
33 if (!service) {
34 return PSA_ERROR_CONNECTION_REFUSED;
35 }
36
37 /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
38 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
39 return PSA_ERROR_PROGRAMMER_ERROR;
40 }
41
42 /*
43 * It is a PROGRAMMER ERROR if the caller is not authorized to access the
44 * RoT Service.
45 */
46 if (tfm_spm_check_authorization(sid, service, ns_caller) != PSA_SUCCESS) {
47 return PSA_ERROR_CONNECTION_REFUSED;
48 }
49
50 /*
51 * It is a PROGRAMMER ERROR if the version of the RoT Service requested is
52 * not supported on the platform.
53 */
54 if (tfm_spm_check_client_version(service, version) != PSA_SUCCESS) {
55 return PSA_ERROR_CONNECTION_REFUSED;
56 }
57
58 client_id = tfm_spm_get_client_id(ns_caller);
59
60 /*
61 * Create connection handle here since it is possible to return the error
62 * code to client when creation fails.
63 */
64 CRITICAL_SECTION_ENTER(cs_assert);
65 p_connection = spm_allocate_connection();
66 CRITICAL_SECTION_LEAVE(cs_assert);
67 if (!p_connection) {
68 return PSA_ERROR_CONNECTION_BUSY;
69 }
70
71 handle = connection_to_handle(p_connection);
72 spm_fill_message(p_connection, service, handle, PSA_IPC_CONNECT, client_id);
73
74 return backend_messaging(service, p_connection);
75 }
76
tfm_spm_client_psa_close(psa_handle_t handle)77 psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
78 {
79 struct service_t *service;
80 struct connection_t *p_connection;
81 int32_t client_id;
82 bool ns_caller = tfm_spm_is_ns_caller();
83
84 /* It will have no effect if called with the NULL handle */
85 if (handle == PSA_NULL_HANDLE) {
86 return PSA_SUCCESS;
87 }
88
89 /* It is a PROGRAMMER ERROR if called with a stateless handle. */
90 if (IS_STATIC_HANDLE(handle)) {
91 return PSA_ERROR_PROGRAMMER_ERROR;
92 }
93
94 client_id = tfm_spm_get_client_id(ns_caller);
95
96 /*
97 * It is a PROGRAMMER ERROR if an invalid handle was provided that is not
98 * the null handle.
99 */
100 p_connection = spm_get_client_connection(handle, client_id);
101 if (!p_connection) {
102 return PSA_ERROR_PROGRAMMER_ERROR;
103 }
104
105 service = p_connection->service;
106 if (!service) {
107 /* FixMe: Need to implement one mechanism to resolve this failure. */
108 return PSA_ERROR_PROGRAMMER_ERROR;
109 }
110
111 /*
112 * It is a PROGRAMMER ERROR if the connection is currently handling a
113 * request.
114 */
115 if (p_connection->status == TFM_HANDLE_STATUS_ACTIVE) {
116 return PSA_ERROR_PROGRAMMER_ERROR;
117 }
118
119 spm_fill_message(p_connection, service, handle, PSA_IPC_DISCONNECT, client_id);
120
121 return backend_messaging(service, p_connection);
122 }
123
tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle,void * rhandle)124 void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
125 {
126 struct connection_t *handle;
127
128 /* It is a fatal error if message handle is invalid */
129 handle = spm_msg_handle_to_connection(msg_handle);
130 if (!handle) {
131 tfm_core_panic();
132 }
133
134 /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
135 if (SERVICE_IS_STATELESS(handle->service->p_ldinf->flags)) {
136 tfm_core_panic();
137 }
138
139 handle->msg.rhandle = rhandle;
140 handle->rhandle = rhandle;
141 }
142