Update from upstream to 2.4.0 version
[platform/core/security/tef-optee_os.git] / core / arch / arm / tee / pta_socket.c
1 /*
2  * Copyright (c) 2016-2017, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <assert.h>
29 #include <kernel/pseudo_ta.h>
30 #include <optee_msg.h>
31 #include <optee_msg_supplicant.h>
32 #include <pta_socket.h>
33 #include <string.h>
34 #include <tee/tee_fs_rpc.h>
35
36 static uint32_t get_instance_id(struct tee_ta_session *sess)
37 {
38         return sess->ctx->ops->get_instance_id(sess->ctx);
39 }
40
41 static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types,
42                               TEE_Param params[TEE_NUM_PARAMS])
43 {
44         TEE_Result res;
45         paddr_t pa;
46         uint64_t cookie;
47         void *va;
48         struct optee_msg_param msg_params[4];
49         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
50                                           TEE_PARAM_TYPE_MEMREF_INPUT,
51                                           TEE_PARAM_TYPE_VALUE_INPUT,
52                                           TEE_PARAM_TYPE_VALUE_OUTPUT);
53
54         if (exp_pt != param_types) {
55                 DMSG("got param_types 0x%x, expected 0x%x",
56                      param_types, exp_pt);
57                 return TEE_ERROR_BAD_PARAMETERS;
58         }
59
60         memset(msg_params, 0, sizeof(msg_params));
61
62         va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
63         if (!va)
64                 return TEE_ERROR_OUT_OF_MEMORY;
65
66         msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
67         msg_params[0].u.value.a = OPTEE_MRC_SOCKET_OPEN;
68         msg_params[0].u.value.b = instance_id;
69
70         msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
71         msg_params[1].u.value.a = params[0].value.b; /* server port number */
72         msg_params[1].u.value.b = params[2].value.a; /* protocol */
73         msg_params[1].u.value.c = params[0].value.a; /* ip version */
74
75         /* server address */
76         msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
77         msg_params[2].u.tmem.buf_ptr = pa;
78         msg_params[2].u.tmem.size = params[1].memref.size;
79         msg_params[2].u.tmem.shm_ref = cookie;
80         memcpy(va, params[1].memref.buffer, params[1].memref.size);
81
82         /* socket handle */
83         msg_params[3].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
84
85         res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 4, msg_params);
86
87         if (res == TEE_SUCCESS)
88                 params[3].value.a = msg_params[3].u.value.a;
89
90         return res;
91 }
92
93 static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types,
94                                TEE_Param params[TEE_NUM_PARAMS])
95 {
96         struct optee_msg_param msg_params[1];
97         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
98                                           TEE_PARAM_TYPE_NONE,
99                                           TEE_PARAM_TYPE_NONE,
100                                           TEE_PARAM_TYPE_NONE);
101
102         if (exp_pt != param_types) {
103                 DMSG("got param_types 0x%x, expected 0x%x",
104                      param_types, exp_pt);
105                 return TEE_ERROR_BAD_PARAMETERS;
106         }
107
108         memset(msg_params, 0, sizeof(msg_params));
109
110         msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
111         msg_params[0].u.value.a = OPTEE_MRC_SOCKET_CLOSE;
112         msg_params[0].u.value.b = instance_id;
113         msg_params[0].u.value.c = params[0].value.a;
114
115         return thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 1, msg_params);
116 }
117
118 static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types,
119                               TEE_Param params[TEE_NUM_PARAMS])
120 {
121         TEE_Result res;
122         paddr_t pa;
123         uint64_t cookie;
124         void *va;
125         struct optee_msg_param msg_params[3];
126         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
127                                           TEE_PARAM_TYPE_MEMREF_INPUT,
128                                           TEE_PARAM_TYPE_VALUE_OUTPUT,
129                                           TEE_PARAM_TYPE_NONE);
130
131         if (exp_pt != param_types) {
132                 DMSG("got param_types 0x%x, expected 0x%x",
133                      param_types, exp_pt);
134                 return TEE_ERROR_BAD_PARAMETERS;
135         }
136
137         memset(msg_params, 0, sizeof(msg_params));
138
139         va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
140         if (!va)
141                 return TEE_ERROR_OUT_OF_MEMORY;
142
143         msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
144         msg_params[0].u.value.a = OPTEE_MRC_SOCKET_SEND;
145         msg_params[0].u.value.b = instance_id;
146         msg_params[0].u.value.c = params[0].value.a; /* handle */
147
148         /* buffer */
149         msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
150         msg_params[1].u.tmem.buf_ptr = pa;
151         msg_params[1].u.tmem.size = params[1].memref.size;
152         msg_params[1].u.tmem.shm_ref = cookie;
153         memcpy(va, params[1].memref.buffer, params[1].memref.size);
154
155         msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INOUT;
156         msg_params[2].u.value.a = params[0].value.b /* timeout */;
157
158
159         res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 3, msg_params);
160         params[2].value.a = msg_params[2].u.value.b; /* transmitted bytes */
161         return res;
162 }
163
164 static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types,
165                               TEE_Param params[TEE_NUM_PARAMS])
166 {
167         TEE_Result res;
168         paddr_t pa;
169         uint64_t cookie;
170         void *va;
171         struct optee_msg_param msg_params[3];
172         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
173                                           TEE_PARAM_TYPE_MEMREF_OUTPUT,
174                                           TEE_PARAM_TYPE_NONE,
175                                           TEE_PARAM_TYPE_NONE);
176
177         if (exp_pt != param_types) {
178                 DMSG("got param_types 0x%x, expected 0x%x",
179                      param_types, exp_pt);
180                 return TEE_ERROR_BAD_PARAMETERS;
181         }
182
183         memset(msg_params, 0, sizeof(msg_params));
184
185         va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
186         if (!va)
187                 return TEE_ERROR_OUT_OF_MEMORY;
188
189         msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
190         msg_params[0].u.value.a = OPTEE_MRC_SOCKET_RECV;
191         msg_params[0].u.value.b = instance_id;
192         msg_params[0].u.value.c = params[0].value.a; /* handle */
193
194         /* buffer */
195         msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
196         msg_params[1].u.tmem.buf_ptr = pa;
197         msg_params[1].u.tmem.size = params[1].memref.size;
198         msg_params[1].u.tmem.shm_ref = cookie;
199
200         msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
201         msg_params[2].u.value.a = params[0].value.b /* timeout */;
202
203
204         res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 3, msg_params);
205         params[1].memref.size = msg_params[1].u.tmem.size;
206         if (msg_params[1].u.tmem.size)
207                 memcpy(params[1].memref.buffer, va, msg_params[1].u.tmem.size);
208         return res;
209 }
210
211 static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types,
212                                TEE_Param params[TEE_NUM_PARAMS])
213 {
214         TEE_Result res;
215         paddr_t pa;
216         uint64_t cookie;
217         void *va;
218         struct optee_msg_param msg_params[3];
219         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
220                                           TEE_PARAM_TYPE_MEMREF_INOUT,
221                                           TEE_PARAM_TYPE_NONE,
222                                           TEE_PARAM_TYPE_NONE);
223
224         if (exp_pt != param_types) {
225                 DMSG("got param_types 0x%x, expected 0x%x",
226                      param_types, exp_pt);
227                 return TEE_ERROR_BAD_PARAMETERS;
228         }
229
230         memset(msg_params, 0, sizeof(msg_params));
231
232         va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
233         if (!va)
234                 return TEE_ERROR_OUT_OF_MEMORY;
235
236         msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
237         msg_params[0].u.value.a = OPTEE_MRC_SOCKET_IOCTL;
238         msg_params[0].u.value.b = instance_id;
239         msg_params[0].u.value.c = params[0].value.a; /* handle */
240
241         /* buffer */
242         msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INOUT;
243         msg_params[1].u.tmem.buf_ptr = pa;
244         msg_params[1].u.tmem.size = params[1].memref.size;
245         msg_params[1].u.tmem.shm_ref = cookie;
246         memcpy(va, params[1].memref.buffer, params[1].memref.size);
247
248         msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
249         msg_params[2].u.value.a = params[0].value.b; /* ioctl command */
250
251         res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 3, msg_params);
252         if (msg_params[1].u.tmem.size <= params[1].memref.size)
253                 memcpy(params[1].memref.buffer, va, msg_params[1].u.tmem.size);
254         params[1].memref.size = msg_params[1].u.tmem.size;
255         return res;
256 }
257
258 typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types,
259                               TEE_Param params[TEE_NUM_PARAMS]);
260
261 static const ta_func ta_funcs[] = {
262         [PTA_SOCKET_OPEN] = socket_open,
263         [PTA_SOCKET_CLOSE] = socket_close,
264         [PTA_SOCKET_SEND] = socket_send,
265         [PTA_SOCKET_RECV] = socket_recv,
266         [PTA_SOCKET_IOCTL] = socket_ioctl,
267 };
268
269 /*
270  * Trusted Application Entry Points
271  */
272
273 static TEE_Result pta_socket_open_session(uint32_t param_types __unused,
274                         TEE_Param pParams[TEE_NUM_PARAMS] __unused,
275                         void **sess_ctx)
276 {
277         struct tee_ta_session *s;
278
279         /* Check that we're called from a TA */
280         s = tee_ta_get_calling_session();
281         if (!s)
282                 return TEE_ERROR_ACCESS_DENIED;
283
284         *sess_ctx = (void *)(vaddr_t)get_instance_id(s);
285
286         return TEE_SUCCESS;
287 }
288
289 static void pta_socket_close_session(void *sess_ctx)
290 {
291         TEE_Result res;
292         struct optee_msg_param msg_params[1];
293
294         memset(msg_params, 0, sizeof(msg_params));
295
296         msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
297         msg_params[0].u.value.a = OPTEE_MRC_SOCKET_CLOSE_ALL;
298         msg_params[0].u.value.b = (vaddr_t)sess_ctx;
299
300         res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 1, msg_params);
301         if (res != TEE_SUCCESS)
302                 DMSG("OPTEE_MRC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res);
303 }
304
305 static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id,
306                         uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS])
307 {
308         if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id])
309                 return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params);
310
311         return TEE_ERROR_NOT_IMPLEMENTED;
312 }
313
314 pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket",
315                    .flags = PTA_DEFAULT_FLAGS,
316                    .open_session_entry_point = pta_socket_open_session,
317                    .close_session_entry_point = pta_socket_close_session,
318                    .invoke_command_entry_point = pta_socket_invoke_command);