-
Notifications
You must be signed in to change notification settings - Fork 1k
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
core: add new PRC and PTA for loadable plugins framework #4248
Conversation
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.
Hi @anisyanka,
Thanks for the patches. Please see my comments below.
core/include/optee_rpc_cmd.h
Outdated
@@ -139,6 +139,11 @@ | |||
*/ | |||
#define OPTEE_RPC_CMD_FTRACE 11 | |||
|
|||
/* | |||
* Plugin command, see definition of protocol below |
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.
tee-supplicant plugin command ...
core/include/optee_rpc_cmd.h
Outdated
/* | ||
* Plugin command, see definition of protocol below | ||
*/ | ||
#define OPTEE_RPC_CMD_PLUGIN 12 |
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.
OPTEE_RPC_CMD_SUPP_PLUGIN
core/include/optee_rpc_cmd.h
Outdated
* [in] value[2].a sub_cmd for plugin | ||
* [in] memref[3] buffer holding data for plugin | ||
*/ | ||
#define OPTEE_INVOKE_PLUGIN 0 |
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.
For consistency: OPTEE_RPC_SUPP_PLUGIN_INVOKE
core/include/optee_rpc_cmd.h
Outdated
* [in] value[1].b uuid.d4 | ||
* [in] value[1].c cmd for plugin | ||
* [in] value[2].a sub_cmd for plugin | ||
* [in] memref[3] buffer holding data for plugin |
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.
Any chance one would need to return data back to secure world? ([in/out]
).
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.
I think such cases are possible and we should provide the [in/out] ability, thanks
core/include/tee/uuid.h
Outdated
* Returns TEE_SUCCESS, when successfully converting a string or an error code, | ||
* if it has a wrong format or NULL. | ||
*/ | ||
TEE_Result tee_uuid_from_string(TEE_UUID *dst, const char *str, int len); |
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.
This duplicates tee_uuid_from_str()
from lib/libutee/tee_uuid_from_str.c
. If we keep string UUIDs (which I'm not convinced we should), then the implementation could be moved to libutils
I think.
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.
wow, I will try to use the tee_uuid_from_str()
from libutee
:)
In this case I will drop own implementation.
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.
As I said even better would be to not use character strings at all and use a TEE_UUID
instead, unless I am missing something?
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.
TAs work with plugins by its names and that's why the TAs pass the string with name to TEE_InvokeTACommand()
, like here. This string is passed to the plugin-pta.
We can use tee_uuid_from_str()
inside the PTA before calling tee_invoke_plugin_rpc()
.
If we will not use character strings at all in optee, we will need convert the strings in TA, when we want to call plugins.
I don't mind, but seems it looks not convinient for TA developes. What do you think?
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.
You could do:
#define SYSLOG_PLUGIN_UUID { 0x96bcf744, 0x4f72, 0x4866, \
{ 0xbf, 0x1d, 0x86, 0x34, 0xfd, 0x9c, 0x65, 0xe5 } }
...instead of:
#define SYSLOG_PLUGIN_NAME "96bcf744-4f72-4866-bf1d-8634fd9c65e5"
That's how TAs open other TAs or PTAs for example. The only place you may need to convert from binary UUIDs to a string is in tee-supplicant when looking for a plugin (and even in this case it may not be necessary, I mean assuming tee-supplicant enumerates and loads all the plugins on startup, it would convert from plugin name to UUID instead, or find the UUID in the plugin).
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.
OK, got it, thanks!
core/include/tee/tee_plugin_rpc.h
Outdated
#include <tee_api_types.h> | ||
|
||
struct tee_plugin_rpc_operation { | ||
const char *name; /* string "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */ |
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.
Why not use a TEE_UUID
?
core/tee/sub.mk
Outdated
@@ -45,3 +45,4 @@ endif #CFG_WITH_USER_TA,y | |||
|
|||
srcs-y += uuid.c | |||
srcs-y += tee_ta_enc_manager.c | |||
srcs-y += tee_plugin_rpc.c |
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.
tee_supp_plugin_rpc.c
core/include/tee/tee_plugin_rpc.h
Outdated
#include <stdint.h> | ||
#include <tee_api_types.h> | ||
|
||
struct tee_plugin_rpc_operation { |
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.
"supplicant" is missing here, struct supp_plugin_rpc_op
maybe?
And filename could be supp_plugin_rpc.h
.
core/tee/tee_plugin_rpc.c
Outdated
|
||
res = tee_uuid_from_string(&u, op->name, strlen(op->name)); | ||
if (res) { | ||
EMSG("can't convert string <%s> to UUID", op->name); |
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.
You wouldn't need to care about this if you used TEE_UUID
.
core/pta/sub.mk
Outdated
@@ -10,5 +10,6 @@ endif | |||
srcs-$(CFG_WITH_STATS) += stats.c | |||
srcs-$(CFG_SYSTEM_PTA) += system.c | |||
srcs-$(CFG_NXP_SE05X) += scp03.c | |||
srcs-$(CFG_PLUGIN_PTA) += plugin.c |
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.
CFG_SUPP_PLUGIN_PTA += supp_plugin.c
Isn't this providing the same kind of services as proposed by the OCALLs P-Rs (#3673 and related)? |
Thanks for the link. I looked those PRs. The goals of our PRs are similar, but there are important differences:
|
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.
Wouldn't it make sense to add this to the system PTA instead of defining yet another PTA? System PTA is about providing system services to user TAs so it seems like a good match.
core/tee/tee_plugin_rpc.c
Outdated
goto out; | ||
} | ||
|
||
memcpy(&plug_uuid, &u, sizeof(TEE_UUID)); |
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.
I believe tee_uuid_to_octets()
would be a better choice in order to get the correct byte order.
core/tee/tee_plugin_rpc.c
Outdated
uint32_t d2; | ||
uint32_t d3; | ||
uint32_t d4; | ||
} plug_uuid; |
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.
It seems like uint32_t plug_uuid[4] = { };
would be just as useful and a bit simpler.
core/tee/tee_plugin_rpc.c
Outdated
|
||
memcpy(&plug_uuid, &u, sizeof(TEE_UUID)); | ||
|
||
struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS] = { |
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.
Declarations of variables at the start of the block please.
lib/libutee/include/pta_plugin.h
Outdated
* [in] value[1].b sub_command for plugin | ||
* [in] memref[2] additional data for plugin | ||
*/ | ||
#define PTA_PLUGIN_INVOKE 0 |
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.
Wouldn't it be nice with a wrapper in libutee
, something like:
TEE_Result optee_invoke_supp_plugin(const TEE_UUID *uuid, uint32_t cmd, uint32_t sub_cmd,
void *buf, size_t len);
lib/libutee/include/pta_plugin.h
Outdated
* [in] memref[0].size length of the uuid string including '\0' symbol | ||
* [in] value[1].a command for plugin | ||
* [in] value[1].b sub_command for plugin | ||
* [in] memref[2] additional data for plugin |
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.
Shouldn't this be in and out?
Sounds good. I will move |
All comments have been addressed |
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.
Minor comments
*/ | ||
|
||
#ifndef TEE_PLUGIN_RPC_H | ||
#define TEE_PLUGIN_RPC_H |
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.
TEE_SUPP_PLUGIN_RPC_H
core/pta/system.c
Outdated
static TEE_Result system_supp_plugin_invoke(uint32_t param_types, | ||
TEE_Param params[TEE_NUM_PARAMS]) | ||
{ | ||
struct tee_supp_plugin_rpc_op op; |
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.
= { };
core/tee/tee_supp_plugin_rpc.c
Outdated
#include <tee/tee_supp_plugin_rpc.h> | ||
#include <tee/uuid.h> | ||
#include <trace.h> | ||
#include <mm/mobj.h> |
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.
move before line 8
core/tee/tee_supp_plugin_rpc.c
Outdated
{ | ||
TEE_Result res = TEE_ERROR_GENERIC; | ||
struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS]; | ||
uint32_t plugin_uuid[4]; |
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.
= { 0 };
core/tee/tee_supp_plugin_rpc.c
Outdated
uint32_t plugin_uuid[4]; | ||
void *va = NULL; | ||
struct mobj *mobj = NULL; | ||
uint32_t outlen; |
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.
= 0;
lib/libutee/tee_system_pta.c
Outdated
res = invoke_system_pta(PTA_SYSTEM_SUPP_PLUGIN_INVOKE, param_types, | ||
params); | ||
if (res) | ||
EMSG("Invoke tee-supplicant's plugin failed"); |
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.
I would make it a DMSG()
:
DMSG("Invoke tee-supplicant's plugin failed: %#"PRIx32, res);
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.
Could you please explain why you want to use DMSG()
instead EMSG()
?
In this case we print the error message, that's why it seems EMSG
is more suitable.
lib/libutee/include/pta_system.h
Outdated
/* | ||
* Invoke a tee-supplicant's plugin | ||
* | ||
* [in] memref[0] uuid(octets) of the plugin |
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.
Specify that it's a TEE_UUID to be clear.
* @cmd: command for the plugin | ||
* @sub_cmd: subcommand for the plugin | ||
* @buf: data [for/from] the plugin [in/out] | ||
* @len: length of the buf |
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.
Should this be an out parameter too, in case the size is smaller when returning some result?
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.
I think yes.
We can replace size_t len
to size_t *len
and use one pointer to input and output length.
core/tee/tee_supp_plugin_rpc.c
Outdated
#include <trace.h> | ||
#include <mm/mobj.h> | ||
|
||
TEE_Result tee_invoke_supp_plugin_rpc(struct tee_supp_plugin_rpc_op *op) |
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.
Why is this function taking a struct tee_supp_plugin_rpc_op
only used for this purpose instead of separate parameters?
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.
I think we can use separate parameters here. Ok, I will drop tee_supp_plugin_rpc_op
All comments have been addressed |
core/pta/system.c
Outdated
params[1].value.b, /* sub_cmd */ | ||
params[2].memref.buffer, /* data */ | ||
params[2].memref.size, /* in len */ | ||
(size_t *)¶ms[3].value.a |
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.
This cast isn't portable.
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.
Yes, you are right. I will fix it
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.
I'm sorry, I should have been more clear. Please use a temporary helper variable instead of changing the type in the argument of tee_invoke_supp_plugin_rpc()
.
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.
It seems you see outdated changes.
In previous commits I changed outlen
type for tee_invoke_supp_plugin_rpc()
from size_t *
to uint32_t *
and removed type conversion in core/pta/system.c:863
. See the last fixup commit: 3a46040#diff-80ee4f614b595d036997a8c22e8034f37acf85250c5829593e630cab71a9bb4aR863.
I can return back size_t *
and add temporary helper variable, if it will be better.
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.
I can return back size_t * and add temporary helper variable, if it will be better.
Please do so.
core/tee/tee_supp_plugin_rpc.c
Outdated
memcpy(va, buf, len); | ||
} | ||
|
||
plugin_uuid = (uint32_t *)uuid; |
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.
I believe you need to do something like:
uint32_t uuid_words[4] = { };
tee_uuid_to_octets(uuid_words, uuid);
Secure world is always in little endian so there's no need for any more byte swapping.
Later when decoding this in tee-supplicant you'd do something like:
TEEC_UUID uuid = { };
uint32_t uuid_words[4] = { };
uuid_words[0] = from_le32(params[0].b);
...
tee_uuid_from_octets(&uuid, (void *)uuid_words);
This should work for both a big and little endian normal world. Other parts in the chain (driver) are missing so a big endian normal world wouldn't work for other reasons, but we shouldn't make it harder than necessary in case we'd ever fix that.
Do it make sense?
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.
Yes, it make sense. I added le32toh()
to tee-supplicant when decoding uuid_words[].
core/include/optee_rpc_cmd.h
Outdated
* [out] value[2].b length of the outbuf (memref[3]), if out is needed. | ||
* [in/out] memref[3] buffer holding data for plugin | ||
* | ||
* Serialized bytes of the TEE_UUID: |
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.
Might be more clear to say: "UUID serialized into octets".
This is not to be confused with the in memory representation of TEE_UUID
.
All comments have been addressed |
|
Any external TEE services can be designed as a tee-supplicant plugin. The plugins will be loaded by the supplicant during startup process using libdl. It makes it easy to: - add new features in the supplicant that aren't needed in upstream, e.g. Rich OS specific services; - sync upstream version with own fork; This patch adds a new RPC - 'OPTEE_RPC_CMD_SUPP_PLUGIN' as an unified interface between OP-TEE and any plugins. Kernel code can use it to call for execution of some command in plugins. Every plugin has own name based on UUID. OP-TEE has access to plugins by it. See definition of protocol for the plugin RPC command in 'core/include/optee_rpc_cmd.h' file. Signed-off-by: Aleksandr Anisimov <a.anisimov@omprussia.ru> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
This patch adds a new API to libutee to interact with tee-supplicant plugins from TEE userspace. Every user TA can use 'tee_invoke_supp_plugin()' to send any commands to a plugin. The commands are predefined by the plugin developer. See the https://github.com/linaro-swg/optee_examples repo for an example of using plugins. Signed-off-by: Aleksandr Anisimov <a.anisimov@omprussia.ru> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
The commits reworded. |
@anisyanka thanks for your contribution. |
Any external TEE services can be designed as a tee-supplicant plugin.
The plugins will be loaded by the supplicant during startup process
using libdl.
It makes it easy to:
e.g. Rich OS specific services;
These patches add a new RPC - 'OPTEE_RPC_CMD_PLUGIN' as an unified
interface between OP-TEE and any plugins and a new PTA as an unified
interface between any user's TAs and any plugins.
Kernel code can use RPC directly to call for execution of some command in plugins.
TAs can use the plugin-pta.
Every plugin has own name based on UUID.
OP-TEE has access to plugins by it.
See definition of protocol for the command 'OPTEE_RPC_CMD_PLUGIN'
in 'core/include/optee_rpc_cmd.h' file.
Signed-off-by: Aleksandr Anisimov a.anisimov@omprussia.ru