-
Notifications
You must be signed in to change notification settings - Fork 259
[RFC] tee-supplicant: add support for accessing custom REE service #170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,8 @@ LIB_MAJ_MIN := $(LIB_NAME).$(MAJOR_VERSION).$(MINOR_VERSION) | |
| LIB_MAJ_MIN_P := $(LIB_NAME).$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) | ||
|
|
||
| TEEC_SRCS := tee_client_api.c \ | ||
| teec_trace.c | ||
| teec_trace.c \ | ||
| ree_service_api.c | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alphabetical order preferred, please |
||
| ifeq ($(CFG_TEE_BENCHMARK),y) | ||
| TEEC_SRCS += teec_benchmark.c | ||
| endif | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,255 @@ | ||
|
|
||
| #include <sys/types.h> | ||
| #include <sys/ipc.h> | ||
| #include <sys/msg.h> | ||
| #include <stdlib.h> | ||
| #include <errno.h> | ||
|
|
||
| #include <tee_client_api.h> | ||
| #include <teec_trace.h> | ||
| #include <ree_service_api.h> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alphabetical order preferred, please |
||
|
|
||
| #ifndef __aligned | ||
| #define __aligned(x) __attribute__((__aligned__(x))) | ||
| #endif | ||
| #include <linux/tee.h> | ||
|
|
||
| struct service { | ||
| int msgqid; | ||
| void *buf; | ||
| size_t buf_sz; | ||
| }; | ||
|
|
||
| static bool is_param_type_value(uint64_t param_type) | ||
| { | ||
| if (param_type == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || | ||
| param_type == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT || | ||
| param_type == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT) | ||
| return true; | ||
| return false; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor style: prefer a switch/case, here and in switch (param_type) {
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
return true;
default:
return false;
}Also rename Same comment for equivalent functions in
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have modified optee-examples and optee_os, and came here. I used
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency with other OP-TEE OS source, I suggest to use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's just a static function so anything within reason goes. I think that |
||
| } | ||
|
|
||
| static bool is_param_type_memref(uint64_t param_type) | ||
| { | ||
| if (param_type == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || | ||
| param_type == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT || | ||
| param_type == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT) | ||
| return true; | ||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * uuid_to_str() - convert uuid structure to string | ||
| * | ||
| * Example uuid: 2aa2685c-fba3-44be-a218-fbdafebd639a | ||
| * Convert the structure to the string form as above | ||
| */ | ||
| TEEC_Result uuid_to_str(REEC_UUID *uuid, char *uuid_str, size_t size) | ||
| { | ||
| uint32_t i, idx; | ||
|
|
||
| if (!uuid || !uuid_str) | ||
| return TEEC_ERROR_BAD_PARAMETERS; | ||
|
|
||
| /* Convert to the uuid string */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: seems simpler with less snprintf(uuid_str, size, "%08x-%04x-%04x-%02x%02x-",
uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion);
idx = strlen(uuid_str);
snprintf(uuid_str + idx, size - idx, "%02x%02x%02x%02x%02x%02x%02x%02x",
uuid->clockSeqAndNode[0], uuid->clockSeqAndNode[1],
uuid->clockSeqAndNode[2], uuid->clockSeqAndNode[3],
uuid->clockSeqAndNode[4], uuid->clockSeqAndNode[5],
uuid->clockSeqAndNode[6], uuid->clockSeqAndNode[7]); |
||
| snprintf(uuid_str, size, "%08x-", uuid->timeLow); | ||
| idx = strlen(uuid_str); | ||
|
|
||
| snprintf(uuid_str + idx, size - idx, "%04x-", uuid->timeMid); | ||
| idx = strlen(uuid_str); | ||
|
|
||
| snprintf(uuid_str + idx, size - idx, | ||
| "%04x-", uuid->timeHiAndVersion); | ||
| idx = strlen(uuid_str); | ||
|
|
||
| snprintf(uuid_str + idx, size, | ||
| "%02x%02x-", uuid->clockSeqAndNode[0], | ||
| uuid->clockSeqAndNode[1]); | ||
| idx = strlen(uuid_str); | ||
|
|
||
| for (i = 2; i < 8; i++) { | ||
| snprintf(uuid_str + idx, size - idx, | ||
| "%02x", uuid->clockSeqAndNode[i]); | ||
| idx = strlen(uuid_str); | ||
| } | ||
|
|
||
| return TEEC_SUCCESS; | ||
| } | ||
|
|
||
| TEEC_Result ree_service_init(REEC_UUID *uuid, void **service) | ||
| { | ||
| int ret = -1; | ||
| size_t size; | ||
| FILE *fp = NULL; | ||
| char filename[64]; | ||
| key_t msgqkey = 0; | ||
| TEEC_Result result; | ||
| char uuid_str[48]; | ||
|
|
||
| result = uuid_to_str(uuid, uuid_str, sizeof(uuid_str)); | ||
| if (result != TEEC_SUCCESS) | ||
| return result; | ||
|
|
||
| struct service *s = malloc(sizeof(struct service)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: prefer declaration at function entry.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bad miss. |
||
| if (!s) | ||
| return -ENOMEM; | ||
|
|
||
| /* Create a file in /data/<uuid> */ | ||
| snprintf(filename, sizeof(filename), "/data/%s", uuid_str); | ||
| fp = fopen(filename, "w"); | ||
| if (!fp) { | ||
| printf("Failed to create a file for token\n"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prefer the optee log macros |
||
| goto err; | ||
| } | ||
|
|
||
| size = fwrite(uuid_str, 1, strlen(uuid_str), fp); | ||
| if (size != strlen(uuid_str)) { | ||
| printf("Failed to write to %s\n", filename); | ||
| result = TEEC_ERROR_GENERIC; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed error handling all over. |
||
| goto err; | ||
| } | ||
|
|
||
| if (fclose(fp)) { | ||
| printf("Failed to commit data to storage\n"); | ||
| result = TEEC_ERROR_GENERIC; | ||
| goto err; | ||
| } | ||
|
|
||
| /* Create a message queue and wait for the msg */ | ||
| msgqkey = ftok(filename, 'O'); | ||
| if (msgqkey == -1) { | ||
| printf("Failed to create a msg queue key (%d: %s)\n", | ||
| errno, strerror(errno)); | ||
| result = TEEC_ERROR_GENERIC; | ||
| goto err; | ||
| } | ||
|
|
||
| s->msgqid = msgget(msgqkey, 0600 | IPC_CREAT); | ||
| if (s->msgqid == -1) { | ||
| printf("Failed to get the msg queue\n"); | ||
| result = TEEC_ERROR_GENERIC; | ||
| goto err; | ||
| } | ||
|
|
||
| *service = s; | ||
|
|
||
| return 0; | ||
|
|
||
| err: | ||
| if (s) | ||
| free(s); | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| void ree_service_exit(void *service) | ||
| { | ||
| struct service *s = service; | ||
|
|
||
| if (!s) | ||
| return; | ||
|
|
||
| if (s->msgqid != -1) { | ||
| if (msgctl(s->msgqid, IPC_RMID, NULL) == -1) | ||
| printf("Failed to delete msgq, try using ipcrm\n"); | ||
| } | ||
|
|
||
| if (s->buf) | ||
| free(s->buf); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor style: remove the test, calling |
||
|
|
||
| free(s); | ||
| } | ||
|
|
||
| TEEC_Result ree_rcv_params(void *service, size_t *num_params, | ||
| struct tee_params *params) | ||
| { | ||
| int ret, idx = 0; | ||
| char *buf = NULL, *ptr; | ||
| struct service *s = service; | ||
| long msg_size[2] = {0}; | ||
| size_t size, attr_sz, value_sz, mtype_sz = sizeof(long); | ||
|
|
||
| if (!s || !num_params || !params) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The service caller expects us to fill |
||
| return TEEC_ERROR_BAD_PARAMETERS; | ||
|
|
||
| attr_sz = sizeof(params->attr); | ||
| value_sz = sizeof(params->u.value); | ||
|
|
||
| /* The first message will tell the size of buffer */ | ||
| ret = msgrcv(s->msgqid, &msg_size, | ||
| sizeof(msg_size[1]), OPTEE_MRC_MSG_SEND, 0); | ||
| if (ret == -1) { | ||
| printf("Failed to get the size of buffer\n"); | ||
| goto err; | ||
| } | ||
| size = msg_size[1]; | ||
| s->buf_sz = size; | ||
|
|
||
| buf = calloc(size, 1); | ||
| if (!buf) { | ||
| printf("Out of memory to receive message\n"); | ||
| goto err; | ||
| } | ||
|
|
||
| /* The second message will retrive full contents */ | ||
| ret = msgrcv(s->msgqid, buf, size - mtype_sz, OPTEE_MRC_MSG_SEND, 0); | ||
| if (ret == -1) { | ||
| printf("Failed to receive msg\n"); | ||
| goto err; | ||
| } | ||
|
|
||
| /* Real params start from here: buf + mtype_sz */ | ||
| for (ptr = buf + mtype_sz; ptr < buf + size - sizeof(TEEC_Result);) { | ||
|
|
||
| if (is_param_type_value(*(long *)ptr)) { | ||
|
|
||
| memcpy(¶ms[idx].attr, ptr, attr_sz); | ||
| ptr += attr_sz; | ||
|
|
||
| memcpy(¶ms[idx].u.value, ptr, value_sz); | ||
| ptr += value_sz; | ||
|
|
||
| } else if (is_param_type_memref(*(long *)ptr)) { | ||
|
|
||
| memcpy(¶ms[idx].attr, ptr, attr_sz); | ||
| ptr += attr_sz; | ||
|
|
||
| params[idx].u.memref.size = *(size_t *)ptr; | ||
| params[idx].u.memref.buffer = ptr + | ||
| sizeof(params[idx].u.memref.size); | ||
| ptr = (char *)params[idx].u.memref.buffer + | ||
| params[idx].u.memref.size; | ||
| } | ||
| idx++; | ||
| if (idx == 4) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| break; | ||
| } | ||
|
|
||
| s->buf = buf; | ||
| *num_params = idx; | ||
| return 0; | ||
|
|
||
| err: | ||
| if (buf) | ||
| free(buf); | ||
| return TEEC_ERROR_GENERIC; | ||
| } | ||
|
|
||
| TEEC_Result ree_snd_params(void *service, size_t num_params, | ||
| struct tee_params *params, int32_t error) | ||
| { | ||
| struct service *s = service; | ||
| size_t mtype_sz = sizeof(long); | ||
|
|
||
| (void)num_params; | ||
| (void)params; | ||
| (void)error; | ||
|
|
||
| *(TEEC_Result *)((uint8_t *)s->buf + s->buf_sz - sizeof(TEEC_Result)) = error; | ||
|
|
||
| *((long *)s->buf) = OPTEE_MRC_MSG_RCV; | ||
| if (msgsnd(s->msgqid, s->buf, s->buf_sz - mtype_sz, 0) == -1) | ||
| printf("Failed to send the response\n"); | ||
|
|
||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| #ifndef __REE_SERVICE_H__ | ||
| #define __REE_SERVICE_H__ | ||
|
|
||
| /* | ||
| * Attributes for struct tee_ioctl_param, selects field in the union | ||
| */ | ||
| #define TEE_PARAM_ATTR_TYPE_NONE 0 /* parameter not used */ | ||
|
|
||
| /* | ||
| * These defines value parameters (struct tee_ioctl_param_value) | ||
| */ | ||
| #define TEE_PARAM_ATTR_TYPE_VALUE_INPUT 1 | ||
| #define TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT 2 | ||
| #define TEE_PARAM_ATTR_TYPE_VALUE_INOUT 3 /* input and output */ | ||
|
|
||
| /* | ||
| * These defines shared memory reference parameters (struct | ||
| * tee_ioctl_param_memref) | ||
| */ | ||
| #define TEE_PARAM_ATTR_TYPE_MEMREF_INPUT 5 | ||
| #define TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT 6 | ||
| #define TEE_PARAM_ATTR_TYPE_MEMREF_INOUT 7 /* input and output */ | ||
| struct tee_param_memref { | ||
| void *buffer; | ||
| uint64_t size; | ||
| }; | ||
|
|
||
| struct tee_param_value { | ||
| uint64_t a; | ||
| uint64_t b; | ||
| uint64_t c; | ||
| }; | ||
|
|
||
| struct tee_params { | ||
| uint64_t attr; | ||
| union { | ||
| struct tee_param_memref memref; | ||
| struct tee_param_value value; | ||
| } u; | ||
| }; | ||
|
|
||
| TEEC_Result uuid_to_str(REEC_UUID *uuid, char *uuid_str, size_t size); | ||
| TEEC_Result ree_service_init(REEC_UUID *uuid, void **service); | ||
| void ree_service_exit(void *service); | ||
| TEEC_Result ree_rcv_params(void *service, size_t *num_params, | ||
| struct tee_params *params); | ||
| TEEC_Result ree_snd_params(void *service, size_t num_params, | ||
| struct tee_params *params, int32_t error); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
More general question: where is the actual service executed, in which context? As far as I can tell, you have two modes:
Is this correct? I think these function should be commented so it's clear who should use them and for which scenario. What if someone needs to run the service in kernel space? (i.e., TA wants to talk to a Linux driver). That's a use case I've heard before.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sure.
Yes. The example code is in linaro-swg/optee_examples#63. I will fork out a new directory in
Sure.
Hmm, for now, I didn't had this requirement, but as I understand, it will involve patching |
||
|
|
||
| /* | ||
| * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_GENERIC | ||
| */ | ||
|
|
||
| /* | ||
| * Open REE Service | ||
| * | ||
| * [in] param[0].u.value.a OPTEE_MRC_GENERIC_OPEN | ||
| * [in] param[0].u.value.b TA instance id | ||
| * [out] param[1].u.value.c service handle | ||
| */ | ||
| #define OPTEE_MRC_GENERIC_SERVICE_START 3 | ||
|
|
||
| /* | ||
| * Close REE Service | ||
| * | ||
| * [in] param[0].u.value.a OPTEE_MRC_GENERIC_CLOSE | ||
| * [in] param[0].u.value.b TA instance id | ||
| */ | ||
| #define OPTEE_MRC_GENERIC_SERVICE_STOP 4 | ||
|
|
||
| /* mtype for message queue message exchange */ | ||
| #define OPTEE_MRC_MSG_SEND 1 /* send params to service */ | ||
| #define OPTEE_MRC_MSG_RCV 2 /* receive params from service */ | ||
|
|
||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -270,6 +270,8 @@ typedef struct { | |
| uint8_t clockSeqAndNode[8]; | ||
| } TEEC_UUID; | ||
|
|
||
| typedef TEEC_UUID REEC_UUID; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not needed
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added to differentiate whose UUID it is. Currently, with the name it always seems it is of TEE. I will remove it. |
||
|
|
||
| /** | ||
| * struct TEEC_SharedMemory - Memory to transfer data between a client | ||
| * application and trusted code. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,8 @@ set (SRC | |
| src/tee_supp_fs.c | ||
| src/tee_supplicant.c | ||
| src/teec_ta_load.c | ||
| src/tee_service.c | ||
| src/tee_service_handle.c | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ordering, and name could be better.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used |
||
| ) | ||
|
|
||
| if (CFG_GP_SOCKETS) | ||
|
|
@@ -86,6 +88,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE src) | |
|
|
||
| target_link_libraries (${PROJECT_NAME} | ||
| PRIVATE teec | ||
| PRIVATE dl | ||
| PRIVATE optee-client-headers) | ||
|
|
||
| ################################################################################ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alphabetical order preferred, please