2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Krzysztof Dynowski <k.dynowski@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
19 #include <tef/tee_client_api.h>
25 #include <linux/limits.h>
26 #include <sys/types.h>
31 #include "simulator/creators.h"
32 #include "optee/creators.h"
34 #define TEF_CONFIG_FILE "/etc/tef/tef.conf"
35 #define TEF_CONFIG_MAXLINE 1024
36 #define TEF_LIB_PATH LIB_INSTALL_DIR "/tef"
37 #define TEF_IMPLEMENTATION_SONAME "libteec.so"
38 #define TEEC_SYMBOL(lib, name) *((void**)&lib.w##name) = dlsym(lib.handle, "TEEC_" #name)
44 void *(*createContext)();
45 void *(*createSession)();
46 void *(*createOperation)();
47 void *(*createSharedMemory)();
48 uint32_t (*paramTypes)(uint32_t);
50 TEEC_Result (*wInitializeContext)(const char *name, TEEC_Context *context);
51 void (*wFinalizeContext)(TEEC_Context *context);
52 TEEC_Result (*wOpenSession)(TEEC_Context *context,
53 TEEC_Session *session,
54 const TEEC_UUID *destination,
55 uint32_t connectionMethod,
56 const void *connectionData,
57 TEEC_Operation *operation,
58 uint32_t *returnOrigin);
59 void (*wCloseSession)(TEEC_Session *session);
60 TEEC_Result (*wInvokeCommand)(TEEC_Session *session,
62 TEEC_Operation *operation,
63 uint32_t *returnOrigin);
64 TEEC_Result (*wRegisterSharedMemory)(TEEC_Context *context, TEEC_SharedMemory *sharedMemory);
65 TEEC_Result (*wAllocateSharedMemory)(TEEC_Context *context, TEEC_SharedMemory *sharedMemory);
66 void (*wReleaseSharedMemory)(TEEC_SharedMemory *sharedMemory);
67 void (*wRequestCancellation)(TEEC_Operation *operation);
70 static TEF_LibraryImpl lib;
77 TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context)
79 if (lib.handle == NULL) {
80 return TEEC_ERROR_NOT_IMPLEMENTED;
82 if (context == NULL) {
83 return TEEC_ERROR_BAD_PARAMETERS;
85 context->imp = lib.createContext();
86 TEEC_Result result = lib.wInitializeContext(name, (TEEC_Context *)context->imp);
87 if (result != TEEC_SUCCESS) {
95 void TEEC_FinalizeContext(TEEC_Context *context)
97 if (lib.handle == NULL || context == NULL) {
100 lib.wFinalizeContext((TEEC_Context *)context->imp);
102 memset(context, 0, sizeof(*context));
105 static void freeSession(TEF_SessionImpl *tefSession);
106 static TEF_SessionImpl *allocSession(TEEC_Session *session)
108 TEF_SessionImpl *tefSession = (TEF_SessionImpl *)malloc(sizeof(TEF_SessionImpl));
110 tefSession->implementation = lib.createSession();
111 tefSession->lastOperation = lib.createOperation();
112 if (tefSession->implementation == NULL || tefSession->lastOperation == NULL) {
113 freeSession(tefSession);
116 session->imp = tefSession;
121 static void freeSession(TEF_SessionImpl *tefSession)
123 if (tefSession == NULL) {
126 free(tefSession->lastOperation);
127 tefSession->lastOperation = NULL;
128 free(tefSession->implementation);
129 tefSession->implementation = NULL;
133 static TEEC_Operation *setOperation(TEF_SessionImpl *tefSession, TEEC_Operation *operation)
135 if (operation == NULL) {
139 operation->imp = tefSession->lastOperation;
140 TEEC_Operation *op = (TEEC_Operation *)operation->imp;
141 op->started = operation->started;
142 op->paramTypes = lib.paramTypes(operation->paramTypes);
143 for (int i = 0; i < 4; ++i) {
144 uint8_t type = TEEC_PARAM_TYPE_GET(operation->paramTypes, i);
145 if (type >= TEEC_MEMREF_WHOLE && type <= TEEC_MEMREF_PARTIAL_INOUT) {
146 op->params[i].memref.parent = (TEEC_SharedMemory*)operation->params[i].memref.parent->imp;
147 op->params[i].memref.size = operation->params[i].memref.size;
148 op->params[i].memref.offset = operation->params[i].memref.offset;
150 op->params[i] = operation->params[i];
155 static void getOperation(TEEC_Operation *operation)
157 if (operation == NULL) {
161 TEEC_Operation *op = (TEEC_Operation *)operation->imp;
162 operation->started = op->started;
163 for (int i = 0; i < 4; ++i) {
164 uint8_t type = TEEC_PARAM_TYPE_GET(operation->paramTypes, i);
165 if (type >= TEEC_MEMREF_WHOLE && type <= TEEC_MEMREF_PARTIAL_INOUT) {
166 operation->params[i].memref.size = op->params[i].memref.size;
167 operation->params[i].memref.offset = op->params[i].memref.offset;
169 operation->params[i] = op->params[i];
174 TEEC_Result TEEC_OpenSession(TEEC_Context *context,
175 TEEC_Session *session,
176 const TEEC_UUID *destination,
177 uint32_t connectionMethod,
178 const void *connectionData,
179 TEEC_Operation *operation,
180 uint32_t *returnOrigin)
182 if (returnOrigin != NULL) {
183 *returnOrigin = TEEC_ORIGIN_API;
185 if (lib.handle == NULL) {
186 return TEEC_ERROR_NOT_IMPLEMENTED;
188 if (context == NULL || session == NULL || context->imp == NULL) {
189 return TEEC_ERROR_BAD_PARAMETERS;
191 TEF_SessionImpl *tefSession = allocSession(session);
192 if (tefSession == NULL) {
193 return TEEC_ERROR_OUT_OF_MEMORY;
195 TEEC_Operation *op = setOperation(tefSession, operation);
196 TEEC_Result result = lib.wOpenSession((TEEC_Context *)context->imp,
197 (TEEC_Session *)tefSession->implementation,
198 destination, connectionMethod, connectionData, op, returnOrigin);
199 if (result != TEEC_SUCCESS) {
200 freeSession(tefSession);
203 getOperation(operation);
209 void TEEC_CloseSession(TEEC_Session *session)
211 if (lib.handle == NULL || session == NULL) {
214 TEF_SessionImpl *tefSession = (TEF_SessionImpl *)session->imp;
215 if (tefSession == NULL) {
218 lib.wCloseSession((TEEC_Session *)tefSession->implementation);
219 freeSession(tefSession);
220 memset(session, 0, sizeof(*session));
224 TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
226 TEEC_Operation *operation,
227 uint32_t *returnOrigin)
229 if (returnOrigin != NULL) {
230 *returnOrigin = TEEC_ORIGIN_API;
232 if (lib.handle == NULL) {
233 return TEEC_ERROR_NOT_IMPLEMENTED;
235 TEF_SessionImpl *tefSession = (TEF_SessionImpl *)session->imp;
236 if (tefSession == NULL) {
237 return TEEC_ERROR_BAD_PARAMETERS;
239 TEEC_Operation *op = setOperation(tefSession, operation);
240 TEEC_Result result = lib.wInvokeCommand((TEEC_Session *)tefSession->implementation,
241 commandID, op, returnOrigin);
242 if (result == TEEC_SUCCESS) {
243 getOperation(operation);
249 TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
250 TEEC_SharedMemory *sharedMemory)
252 if (lib.handle == NULL) {
253 return TEEC_ERROR_NOT_IMPLEMENTED;
255 if (sharedMemory == NULL) {
256 return TEEC_ERROR_BAD_PARAMETERS;
258 sharedMemory->imp = lib.createSharedMemory();
259 if (sharedMemory->imp == NULL) {
260 return TEEC_ERROR_OUT_OF_MEMORY;
262 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)sharedMemory->imp;
263 shm->buffer = sharedMemory->buffer;
264 shm->size = sharedMemory->size;
265 shm->flags = sharedMemory->flags;
266 TEEC_Result result = lib.wRegisterSharedMemory((TEEC_Context *)context->imp, shm);
267 if (result != TEEC_SUCCESS) {
268 free(sharedMemory->imp);
269 sharedMemory->imp = NULL;
275 TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
276 TEEC_SharedMemory *sharedMemory)
278 if (lib.handle == NULL) {
279 return TEEC_ERROR_NOT_IMPLEMENTED;
281 if (sharedMemory == NULL) {
282 return TEEC_ERROR_BAD_PARAMETERS;
284 sharedMemory->imp = lib.createSharedMemory();
285 if (sharedMemory->imp == NULL) {
286 return TEEC_ERROR_OUT_OF_MEMORY;
288 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)sharedMemory->imp;
290 shm->size = sharedMemory->size;
291 shm->flags = sharedMemory->flags;
292 TEEC_Result result = lib.wAllocateSharedMemory((TEEC_Context *)context->imp, shm);
293 if (result != TEEC_SUCCESS) {
294 free(sharedMemory->imp);
295 sharedMemory->imp = NULL;
297 sharedMemory->buffer = shm->buffer;
303 void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMemory)
305 if (lib.handle == NULL || sharedMemory == NULL || sharedMemory->imp == NULL) {
308 lib.wReleaseSharedMemory(sharedMemory->imp);
309 free(sharedMemory->imp);
310 sharedMemory->imp = NULL;
314 void TEEC_RequestCancellation(TEEC_Operation *operation)
316 if (lib.handle == NULL || operation == NULL || operation->imp == NULL) {
319 lib.wRequestCancellation(operation->imp);
326 static void configParam(const char *p)
331 if (strncmp(p, "lib=", 4) == 0) {
332 const char *libname = p + 4;
333 if (strlen(libname) > sizeof(config.libname) - 1) {
334 fprintf(stderr, "tef-libteec: name to long '%s'\n", libname);
337 strncpy(config.libname, libname, sizeof(config.libname));
338 config.libname[sizeof(config.libname) - 1] = '\0';
342 static void readConfig()
345 memset(&config, 0, sizeof(config));
346 if ((fd = open(TEF_CONFIG_FILE, O_RDONLY)) < 0) {
347 fprintf(stderr, "tef-libteec: can't read config %s\n", TEF_CONFIG_FILE);
351 char buf[TEF_CONFIG_MAXLINE];
354 while ((r = read(fd, buf + l, sizeof(buf) - l)) > 0) {
356 char *p = strchr(buf, '\n');
358 fprintf(stderr, "tef-libteec: config line too long\n");
364 configParam(buf + l);
366 p = strchr(buf + l, '\n');
368 memcpy(buf, buf + l, r - l);
374 static int findLibrary(const char *name, char *libname)
376 snprintf(libname, PATH_MAX, TEF_LIB_PATH "/%s/" TEF_IMPLEMENTATION_SONAME, name);
377 return access(libname, R_OK) == 0;
380 static void loadLibrary(const char *name)
382 char libfile[PATH_MAX];
384 if (findLibrary(name, libfile)) {
385 lib.handle = dlopen(libfile, RTLD_NOW);
386 if (lib.handle == NULL) {
387 fprintf(stderr, "tef-libteec: %s\n", dlerror());
391 fprintf(stderr, "tef-libteec: implementation '%s' not found in " TEF_LIB_PATH "\n", config.libname);
396 if (strcmp(name, "simulator") == 0) {
397 lib.createContext = simulator_TEEC_Context;
398 lib.createSession = simulator_TEEC_Session;
399 lib.createOperation = simulator_TEEC_Operation;
400 lib.createSharedMemory = simulator_TEEC_SharedMemory;
401 lib.paramTypes = simulator_paramTypes;
402 } else if (strcmp(name, "optee") == 0) {
403 lib.createContext = optee_TEEC_Context;
404 lib.createSession = optee_TEEC_Session;
405 lib.createOperation = optee_TEEC_Operation;
406 lib.createSharedMemory = optee_TEEC_SharedMemory;
407 lib.paramTypes = optee_paramTypes;
409 fprintf(stderr, "tef-libteec: implementation '%s' is not supported\n", name);
415 TEEC_SYMBOL(lib, InitializeContext);
416 TEEC_SYMBOL(lib, FinalizeContext);
417 TEEC_SYMBOL(lib, OpenSession);
418 TEEC_SYMBOL(lib, CloseSession);
419 TEEC_SYMBOL(lib, InvokeCommand);
420 TEEC_SYMBOL(lib, RegisterSharedMemory);
421 TEEC_SYMBOL(lib, AllocateSharedMemory);
422 TEEC_SYMBOL(lib, ReleaseSharedMemory);
423 TEEC_SYMBOL(lib, RequestCancellation);
426 // Note: _init() and _fini() are obsolete
427 void __attribute__ ((constructor)) tef_load(void)
429 //read configuration file
432 memset(&lib, 0, sizeof(lib));
433 if (config.libname[0]) {
434 loadLibrary(config.libname);
437 if (lib.handle == NULL) { // fallback to dummy
441 fprintf(stderr, "tef-libteec: linked to %s\n", lib.name);
443 void __attribute__ ((destructor)) tef_unload(void)
445 if (lib.handle != NULL) {
446 dlclose(lib.handle); // decrement refcount to wrapped library
448 memset(&lib, 0, sizeof(lib));