1 /*
2 * Copyright (c) 2014, STMicroelectronics International N.V.
3 * All rights reserved.
4 * Copyright (c) 2015, Linaro Limited
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <assert.h>
31 #include <dirent.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <inttypes.h>
35 #include <prof.h>
36 #include <plugin.h>
37 #include <pthread.h>
38 #include <rpmb.h>
39 #include <stdbool.h>
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/ioctl.h>
45 #include <sys/mman.h>
46 #include <sys/stat.h>
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <tee_client_api.h>
50 #include <teec_ta_load.h>
51 #include <teec_trace.h>
52 #include <tee_socket.h>
53 #include <tee_supp_fs.h>
54 #include <tee_supplicant.h>
55 #include <unistd.h>
56
57 #include "optee_msg_supplicant.h"
58
59 #ifndef __aligned
60 #define __aligned(x) __attribute__((__aligned__(x)))
61 #endif
62 #include <linux/tee.h>
63
64 #define RPC_NUM_PARAMS 5
65
66 #define RPC_BUF_SIZE (sizeof(struct tee_iocl_supp_send_arg) + \
67 RPC_NUM_PARAMS * sizeof(struct tee_ioctl_param))
68
69 union tee_rpc_invoke {
70 uint64_t buf[(RPC_BUF_SIZE - 1) / sizeof(uint64_t) + 1];
71 struct tee_iocl_supp_recv_arg recv;
72 struct tee_iocl_supp_send_arg send;
73 };
74
75 struct tee_shm {
76 int id;
77 void *p;
78 size_t size;
79 bool registered;
80 int fd;
81 struct tee_shm *next;
82 };
83
84 struct thread_arg {
85 int fd;
86 uint32_t gen_caps;
87 bool abort;
88 size_t num_waiters;
89 pthread_mutex_t mutex;
90 };
91
92 struct param_value {
93 uint64_t a;
94 uint64_t b;
95 uint64_t c;
96 };
97
98 static pthread_mutex_t shm_mutex = PTHREAD_MUTEX_INITIALIZER;
99 static struct tee_shm *shm_head;
100
101 static const char *ta_dir;
102
103 static void *thread_main(void *a);
104
num_waiters_inc(struct thread_arg * arg)105 static size_t num_waiters_inc(struct thread_arg *arg)
106 {
107 size_t ret = 0;
108
109 tee_supp_mutex_lock(&arg->mutex);
110 arg->num_waiters++;
111 assert(arg->num_waiters);
112 ret = arg->num_waiters;
113 tee_supp_mutex_unlock(&arg->mutex);
114
115 return ret;
116 }
117
num_waiters_dec(struct thread_arg * arg)118 static size_t num_waiters_dec(struct thread_arg *arg)
119 {
120 size_t ret = 0;
121
122 tee_supp_mutex_lock(&arg->mutex);
123 assert(arg->num_waiters);
124 arg->num_waiters--;
125 ret = arg->num_waiters;
126 tee_supp_mutex_unlock(&arg->mutex);
127
128 return ret;
129 }
130
paged_aligned_alloc(size_t sz)131 static void *paged_aligned_alloc(size_t sz)
132 {
133 void *p = NULL;
134
135 if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz))
136 return p;
137
138 return NULL;
139 }
140
get_value(size_t num_params,struct tee_ioctl_param * params,const uint32_t idx,struct param_value ** value)141 static int get_value(size_t num_params, struct tee_ioctl_param *params,
142 const uint32_t idx, struct param_value **value)
143 {
144 if (idx >= num_params)
145 return -1;
146
147 switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
148 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
149 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
150 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
151 *value = (void *)¶ms[idx].a;
152 return 0;
153 default:
154 return -1;
155 }
156 }
157
find_tshm(int id)158 static struct tee_shm *find_tshm(int id)
159 {
160 struct tee_shm *tshm = NULL;
161
162 tee_supp_mutex_lock(&shm_mutex);
163
164 tshm = shm_head;
165 while (tshm && tshm->id != id)
166 tshm = tshm->next;
167
168 tee_supp_mutex_unlock(&shm_mutex);
169
170 return tshm;
171 }
172
pop_tshm(int id)173 static struct tee_shm *pop_tshm(int id)
174 {
175 struct tee_shm *tshm = NULL;
176 struct tee_shm *prev = NULL;
177
178 tee_supp_mutex_lock(&shm_mutex);
179
180 tshm = shm_head;
181 if (!tshm)
182 goto out;
183
184 if (tshm->id == id) {
185 shm_head = tshm->next;
186 goto out;
187 }
188
189 do {
190 prev = tshm;
191 tshm = tshm->next;
192 if (!tshm)
193 goto out;
194 } while (tshm->id != id);
195 prev->next = tshm->next;
196
197 out:
198 tee_supp_mutex_unlock(&shm_mutex);
199
200 return tshm;
201 }
202
push_tshm(struct tee_shm * tshm)203 static void push_tshm(struct tee_shm *tshm)
204 {
205 tee_supp_mutex_lock(&shm_mutex);
206
207 tshm->next = shm_head;
208 shm_head = tshm;
209
210 tee_supp_mutex_unlock(&shm_mutex);
211 }
212
213 /* Get parameter allocated by secure world */
get_param(size_t num_params,struct tee_ioctl_param * params,const uint32_t idx,TEEC_SharedMemory * shm)214 static int get_param(size_t num_params, struct tee_ioctl_param *params,
215 const uint32_t idx, TEEC_SharedMemory *shm)
216 {
217 struct tee_shm *tshm = NULL;
218 size_t offs = 0;
219 size_t sz = 0;
220
221 if (idx >= num_params)
222 return -1;
223
224 switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
225 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
226 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
227 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
228 break;
229 default:
230 return -1;
231 }
232
233 memset(shm, 0, sizeof(*shm));
234
235 tshm = find_tshm(MEMREF_SHM_ID(params + idx));
236 if (!tshm) {
237 /*
238 * It doesn't make sense to query required size of an
239 * input buffer.
240 */
241 if ((params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) ==
242 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
243 return -1;
244
245 /*
246 * Buffer isn't found, the caller is querying required size
247 * of the buffer.
248 */
249 return 0;
250 }
251
252 sz = MEMREF_SIZE(params + idx);
253 offs = MEMREF_SHM_OFFS(params + idx);
254 if ((sz + offs) < sz)
255 return -1;
256 if ((sz + offs) > tshm->size)
257 return -1;
258
259 shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
260 shm->size = sz;
261 shm->id = MEMREF_SHM_ID(params + idx);
262 shm->buffer = (uint8_t *)tshm->p + offs;
263
264 return 0;
265 }
266
uuid_from_octets(TEEC_UUID * d,const uint8_t s[TEE_IOCTL_UUID_LEN])267 static void uuid_from_octets(TEEC_UUID *d, const uint8_t s[TEE_IOCTL_UUID_LEN])
268 {
269 d->timeLow = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
270 d->timeMid = (s[4] << 8) | s[5];
271 d->timeHiAndVersion = (s[6] << 8) | s[7];
272 memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode));
273 }
274
load_ta(size_t num_params,struct tee_ioctl_param * params)275 static uint32_t load_ta(size_t num_params, struct tee_ioctl_param *params)
276 {
277 int ta_found = 0;
278 size_t size = 0;
279 struct param_value *val_cmd = NULL;
280 TEEC_UUID uuid;
281 TEEC_SharedMemory shm_ta;
282
283 memset(&uuid, 0, sizeof(uuid));
284 memset(&shm_ta, 0, sizeof(shm_ta));
285
286 if (num_params != 2 || get_value(num_params, params, 0, &val_cmd) ||
287 get_param(num_params, params, 1, &shm_ta))
288 return TEEC_ERROR_BAD_PARAMETERS;
289
290 uuid_from_octets(&uuid, (void *)val_cmd);
291
292 size = shm_ta.size;
293 ta_found = TEECI_LoadSecureModule(ta_dir, &uuid, shm_ta.buffer, &size);
294 if (ta_found != TA_BINARY_FOUND) {
295 EMSG(" TA not found");
296 return TEEC_ERROR_ITEM_NOT_FOUND;
297 }
298
299 MEMREF_SIZE(params + 1) = size;
300
301 /*
302 * If a buffer wasn't provided, just tell which size it should be.
303 * If it was provided but isn't big enough, report an error.
304 */
305 if (shm_ta.buffer && size > shm_ta.size)
306 return TEEC_ERROR_SHORT_BUFFER;
307
308 return TEEC_SUCCESS;
309 }
310
alloc_shm(int fd,size_t size)311 static struct tee_shm *alloc_shm(int fd, size_t size)
312 {
313 struct tee_shm *shm = NULL;
314 struct tee_ioctl_shm_alloc_data data;
315
316 memset(&data, 0, sizeof(data));
317
318 shm = calloc(1, sizeof(*shm));
319 if (!shm)
320 return NULL;
321
322 data.size = size;
323 shm->fd = ioctl(fd, TEE_IOC_SHM_ALLOC, &data);
324 if (shm->fd < 0) {
325 free(shm);
326 return NULL;
327 }
328
329 shm->p = mmap(NULL, data.size, PROT_READ | PROT_WRITE, MAP_SHARED,
330 shm->fd, 0);
331 if (shm->p == (void *)MAP_FAILED) {
332 close(shm->fd);
333 free(shm);
334 return NULL;
335 }
336
337 shm->id = data.id;
338 shm->registered = false;
339 return shm;
340 }
341
register_local_shm(int fd,size_t size)342 static struct tee_shm *register_local_shm(int fd, size_t size)
343 {
344 struct tee_shm *shm = NULL;
345 void *buf = NULL;
346 struct tee_ioctl_shm_register_data data;
347
348 memset(&data, 0, sizeof(data));
349
350 buf = paged_aligned_alloc(size);
351 if (!buf)
352 return NULL;
353
354 shm = calloc(1, sizeof(*shm));
355 if (!shm) {
356 free(buf);
357 return NULL;
358 }
359
360 data.addr = (uintptr_t)buf;
361 data.length = size;
362
363 shm->fd = ioctl(fd, TEE_IOC_SHM_REGISTER, &data);
364 if (shm->fd < 0) {
365 free(shm);
366 free(buf);
367 return NULL;
368 }
369
370 shm->p = buf;
371 shm->registered = true;
372 shm->id = data.id;
373
374 return shm;
375 }
376
process_alloc(struct thread_arg * arg,size_t num_params,struct tee_ioctl_param * params)377 static uint32_t process_alloc(struct thread_arg *arg, size_t num_params,
378 struct tee_ioctl_param *params)
379 {
380 struct param_value *val = NULL;
381 struct tee_shm *shm = NULL;
382
383 if (num_params != 1 || get_value(num_params, params, 0, &val))
384 return TEEC_ERROR_BAD_PARAMETERS;
385
386 if (arg->gen_caps & TEE_GEN_CAP_REG_MEM)
387 shm = register_local_shm(arg->fd, val->b);
388 else
389 shm = alloc_shm(arg->fd, val->b);
390
391 if (!shm)
392 return TEEC_ERROR_OUT_OF_MEMORY;
393
394 shm->size = val->b;
395 val->c = shm->id;
396 push_tshm(shm);
397
398 return TEEC_SUCCESS;
399 }
400
process_free(size_t num_params,struct tee_ioctl_param * params)401 static uint32_t process_free(size_t num_params, struct tee_ioctl_param *params)
402 {
403 struct param_value *val = NULL;
404 struct tee_shm *shm = NULL;
405 int id = 0;
406
407 if (num_params != 1 || get_value(num_params, params, 0, &val))
408 return TEEC_ERROR_BAD_PARAMETERS;
409
410 id = val->b;
411
412 shm = pop_tshm(id);
413 if (!shm)
414 return TEEC_ERROR_BAD_PARAMETERS;
415
416 if (shm->registered) {
417 free(shm->p);
418 } else {
419 if (munmap(shm->p, shm->size) != 0) {
420 EMSG("munmap(%p, %zu) failed - Error = %s",
421 shm->p, shm->size, strerror(errno));
422 close(shm->fd);
423 free(shm);
424 return TEEC_ERROR_BAD_PARAMETERS;
425 }
426 }
427
428 close(shm->fd);
429 free(shm);
430 return TEEC_SUCCESS;
431 }
432
433
434
435 /* How many device sequence numbers will be tried before giving up */
436 #define MAX_DEV_SEQ 10
437
open_dev(const char * devname,uint32_t * gen_caps)438 static int open_dev(const char *devname, uint32_t *gen_caps)
439 {
440 int fd = 0;
441 struct tee_ioctl_version_data vers;
442
443 memset(&vers, 0, sizeof(vers));
444
445 fd = open(devname, O_RDWR);
446 if (fd < 0)
447 return -1;
448
449 if (ioctl(fd, TEE_IOC_VERSION, &vers))
450 goto err;
451
452 /* Only OP-TEE supported */
453 if (vers.impl_id != TEE_IMPL_ID_OPTEE)
454 goto err;
455
456 ta_dir = "optee_armtz";
457 if (gen_caps)
458 *gen_caps = vers.gen_caps;
459
460 DMSG("using device \"%s\"", devname);
461 return fd;
462 err:
463 close(fd);
464 return -1;
465 }
466
get_dev_fd(uint32_t * gen_caps)467 static int get_dev_fd(uint32_t *gen_caps)
468 {
469 int fd = 0;
470 char name[PATH_MAX] = { 0 };
471 size_t n = 0;
472
473 for (n = 0; n < MAX_DEV_SEQ; n++) {
474 snprintf(name, sizeof(name), "/dev/teepriv%zu", n);
475 fd = open_dev(name, gen_caps);
476 if (fd >= 0)
477 return fd;
478 }
479 return -1;
480 }
481
usage(int status)482 static int usage(int status)
483 {
484 fprintf(stderr, "Usage: tee-supplicant [-d] [<device-name>]\n");
485 fprintf(stderr, " -d: run as a daemon (fork after successful "
486 "initialization)\n");
487 return status;
488 }
489
process_rpmb(size_t num_params,struct tee_ioctl_param * params)490 static uint32_t process_rpmb(size_t num_params, struct tee_ioctl_param *params)
491 {
492 TEEC_SharedMemory req;
493 TEEC_SharedMemory rsp;
494
495 memset(&req, 0, sizeof(req));
496 memset(&rsp, 0, sizeof(rsp));
497
498 if (get_param(num_params, params, 0, &req) ||
499 get_param(num_params, params, 1, &rsp))
500 return TEEC_ERROR_BAD_PARAMETERS;
501
502 return rpmb_process_request(req.buffer, req.size, rsp.buffer, rsp.size);
503 }
504
read_request(int fd,union tee_rpc_invoke * request)505 static bool read_request(int fd, union tee_rpc_invoke *request)
506 {
507 struct tee_ioctl_buf_data data;
508
509 memset(&data, 0, sizeof(data));
510
511 data.buf_ptr = (uintptr_t)request;
512 data.buf_len = sizeof(*request);
513 if (ioctl(fd, TEE_IOC_SUPPL_RECV, &data)) {
514 EMSG("TEE_IOC_SUPPL_RECV: %s", strerror(errno));
515 return false;
516 }
517 return true;
518 }
519
write_response(int fd,union tee_rpc_invoke * request)520 static bool write_response(int fd, union tee_rpc_invoke *request)
521 {
522 struct tee_ioctl_buf_data data;
523
524 memset(&data, 0, sizeof(data));
525
526 data.buf_ptr = (uintptr_t)&request->send;
527 data.buf_len = sizeof(struct tee_iocl_supp_send_arg) +
528 sizeof(struct tee_ioctl_param) *
529 (__u64)request->send.num_params;
530 if (ioctl(fd, TEE_IOC_SUPPL_SEND, &data)) {
531 EMSG("TEE_IOC_SUPPL_SEND: %s", strerror(errno));
532 return false;
533 }
534 return true;
535 }
536
find_params(union tee_rpc_invoke * request,uint32_t * func,size_t * num_params,struct tee_ioctl_param ** params,size_t * num_meta)537 static bool find_params(union tee_rpc_invoke *request, uint32_t *func,
538 size_t *num_params, struct tee_ioctl_param **params,
539 size_t *num_meta)
540 {
541 struct tee_ioctl_param *p = NULL;
542 size_t n = 0;
543
544 p = (struct tee_ioctl_param *)(&request->recv + 1);
545
546 /* Skip meta parameters in the front */
547 for (n = 0; n < request->recv.num_params; n++)
548 if (!(p[n].attr & TEE_IOCTL_PARAM_ATTR_META))
549 break;
550
551 *func = request->recv.func;
552 *num_params = request->recv.num_params - n;
553 *params = p + n;
554 *num_meta = n;
555
556 /* Make sure that no meta parameters follows a non-meta parameter */
557 for (; n < request->recv.num_params; n++) {
558 if (p[n].attr & TEE_IOCTL_PARAM_ATTR_META) {
559 EMSG("Unexpected meta parameter");
560 return false;
561 }
562 }
563
564 return true;
565 }
566
spawn_thread(struct thread_arg * arg)567 static bool spawn_thread(struct thread_arg *arg)
568 {
569 int e = 0;
570 pthread_t tid;
571
572 memset(&tid, 0, sizeof(tid));
573
574 DMSG("Spawning a new thread");
575
576 /*
577 * Increase number of waiters now to avoid starting another thread
578 * before this thread has been scheduled.
579 */
580 num_waiters_inc(arg);
581
582 e = pthread_create(&tid, NULL, thread_main, arg);
583 if (e) {
584 EMSG("pthread_create: %s", strerror(e));
585 num_waiters_dec(arg);
586 return false;
587 }
588
589 e = pthread_detach(tid);
590 if (e)
591 EMSG("pthread_detach: %s", strerror(e));
592
593 return true;
594 }
595
process_one_request(struct thread_arg * arg)596 static bool process_one_request(struct thread_arg *arg)
597 {
598 size_t num_params = 0;
599 size_t num_meta = 0;
600 struct tee_ioctl_param *params = NULL;
601 uint32_t func = 0;
602 uint32_t ret = 0;
603 union tee_rpc_invoke request;
604
605 memset(&request, 0, sizeof(request));
606
607 DMSG("looping");
608 request.recv.num_params = RPC_NUM_PARAMS;
609
610 /* Let it be known that we can deal with meta parameters */
611 params = (struct tee_ioctl_param *)(&request.send + 1);
612 params->attr = TEE_IOCTL_PARAM_ATTR_META;
613
614 num_waiters_inc(arg);
615
616 if (!read_request(arg->fd, &request))
617 return false;
618
619 if (!find_params(&request, &func, &num_params, ¶ms, &num_meta))
620 return false;
621
622 if (num_meta && !num_waiters_dec(arg) && !spawn_thread(arg))
623 return false;
624
625 switch (func) {
626 case OPTEE_MSG_RPC_CMD_LOAD_TA:
627 ret = load_ta(num_params, params);
628 break;
629 case OPTEE_MSG_RPC_CMD_FS:
630 ret = tee_supp_fs_process(num_params, params);
631 break;
632 case OPTEE_MSG_RPC_CMD_RPMB:
633 ret = process_rpmb(num_params, params);
634 break;
635 case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
636 ret = process_alloc(arg, num_params, params);
637 break;
638 case OPTEE_MSG_RPC_CMD_SHM_FREE:
639 ret = process_free(num_params, params);
640 break;
641 case OPTEE_MSG_RPC_CMD_GPROF:
642 ret = prof_process(num_params, params, "gmon-");
643 break;
644 case OPTEE_MSG_RPC_CMD_SOCKET:
645 ret = tee_socket_process(num_params, params);
646 break;
647 case OPTEE_MSG_RPC_CMD_FTRACE:
648 ret = prof_process(num_params, params, "ftrace-");
649 break;
650 case OPTEE_MSG_RPC_CMD_PLUGIN:
651 ret = plugin_process(num_params, params);
652 break;
653 default:
654 EMSG("Cmd [0x%" PRIx32 "] not supported", func);
655 /* Not supported. */
656 ret = TEEC_ERROR_NOT_SUPPORTED;
657 break;
658 }
659
660 request.send.ret = ret;
661 return write_response(arg->fd, &request);
662 }
663
thread_main(void * a)664 static void *thread_main(void *a)
665 {
666 struct thread_arg *arg = a;
667
668 /*
669 * Now that this thread has been scheduled, compensate for the
670 * initial increase in spawn_thread() before.
671 */
672 num_waiters_dec(arg);
673
674 while (!arg->abort) {
675 if (!process_one_request(arg))
676 arg->abort = true;
677 }
678
679 return NULL;
680 }
681
main(int argc,char * argv[])682 int main(int argc, char *argv[])
683 {
684 struct thread_arg arg = { .fd = -1 };
685 bool daemonize = false;
686 char *dev = NULL;
687 int e = 0;
688 int i = 0;
689
690 e = pthread_mutex_init(&arg.mutex, NULL);
691 if (e) {
692 EMSG("pthread_mutex_init: %s", strerror(e));
693 EMSG("terminating...");
694 exit(EXIT_FAILURE);
695 }
696
697 if (argc > 3)
698 return usage(EXIT_FAILURE);
699
700 for (i = 1; i < argc; i++) {
701 if (!strcmp(argv[i], "-d"))
702 daemonize = true;
703 else if (!strcmp(argv[i], "-h"))
704 return usage(EXIT_SUCCESS);
705 else
706 dev = argv[i];
707 }
708
709 if (daemonize && daemon(0, 0) < 0) {
710 EMSG("daemon(): %s", strerror(errno));
711 exit(EXIT_FAILURE);
712 }
713
714 if (dev) {
715 arg.fd = open_dev(dev, &arg.gen_caps);
716 if (arg.fd < 0) {
717 EMSG("failed to open \"%s\"", argv[1]);
718 exit(EXIT_FAILURE);
719 }
720 } else {
721 arg.fd = get_dev_fd(&arg.gen_caps);
722 if (arg.fd < 0) {
723 EMSG("failed to find an OP-TEE supplicant device");
724 exit(EXIT_FAILURE);
725 }
726 }
727
728 if (plugin_load_all() != 0) {
729 EMSG("failed to load plugins");
730 exit(EXIT_FAILURE);
731 }
732
733 while (!arg.abort) {
734 if (!process_one_request(&arg))
735 arg.abort = true;
736 }
737
738 close(arg.fd);
739
740 return EXIT_FAILURE;
741 }
742
tee_supp_param_is_memref(struct tee_ioctl_param * param)743 bool tee_supp_param_is_memref(struct tee_ioctl_param *param)
744 {
745 switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
746 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
747 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
748 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
749 return true;
750 default:
751 return false;
752 }
753 }
754
tee_supp_param_is_value(struct tee_ioctl_param * param)755 bool tee_supp_param_is_value(struct tee_ioctl_param *param)
756 {
757 switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
758 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
759 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
760 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
761 return true;
762 default:
763 return false;
764 }
765 }
766
tee_supp_param_to_va(struct tee_ioctl_param * param)767 void *tee_supp_param_to_va(struct tee_ioctl_param *param)
768 {
769 struct tee_shm *tshm = NULL;
770 size_t end_offs = 0;
771
772 if (!tee_supp_param_is_memref(param))
773 return NULL;
774
775 end_offs = MEMREF_SIZE(param) + MEMREF_SHM_OFFS(param);
776 if (end_offs < MEMREF_SIZE(param) || end_offs < MEMREF_SHM_OFFS(param))
777 return NULL;
778
779 tshm = find_tshm(MEMREF_SHM_ID(param));
780 if (!tshm)
781 return NULL;
782
783 if (end_offs > tshm->size)
784 return NULL;
785
786 return (uint8_t *)tshm->p + MEMREF_SHM_OFFS(param);
787 }
788
tee_supp_mutex_lock(pthread_mutex_t * mu)789 void tee_supp_mutex_lock(pthread_mutex_t *mu)
790 {
791 int e = pthread_mutex_lock(mu);
792
793 if (e) {
794 EMSG("pthread_mutex_lock: %s", strerror(e));
795 EMSG("terminating...");
796 exit(EXIT_FAILURE);
797 }
798 }
799
tee_supp_mutex_unlock(pthread_mutex_t * mu)800 void tee_supp_mutex_unlock(pthread_mutex_t *mu)
801 {
802 int e = pthread_mutex_unlock(mu);
803
804 if (e) {
805 EMSG("pthread_mutex_unlock: %s", strerror(e));
806 EMSG("terminating...");
807 exit(EXIT_FAILURE);
808 }
809 }
810