-
Notifications
You must be signed in to change notification settings - Fork 236
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
libteec: implement OCALLs #171
Conversation
dd1e278
to
2bafe5f
Compare
781c07a
to
0a7174b
Compare
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 a general comment, looks a fine way to open a session bound to a remote service provider.
I can't tell if it is the best architecture for customized RPC support.`
For the patch series i felt a bit disoriented by ocall, ecall, Ex session references.
What about renaming TEEC_OpenSessionEx()
into TEEC_OpenSessionWithRPC()
?
Same, teec_ecall()
could be renamed into teec_invoke_command_with_rpc()
.
As for the patch series, could you make a series like:
- Preliminary patch for moving the legacy into new
teec_invoke_command()
. - Patch for
TEEC_OpenSessionEx()
and OCALL related. - Patch implementing
teec_ecall()
/teec_invoke_ca_rpc_command()
. - Last patch for TEE capability
TEE_OPTEE_CAP_OCALL
.
Your commit "Detect OCALL support." nicely fits. Maybe rename intoTEE_OPTEE_CAP_CA_RPC
.
I noted some minor style issues, let's see that later.
public/tee_client_api.h
Outdated
* @param p The paramType. | ||
* @param i The i-th parameter to set the type for. | ||
*/ | ||
#define TEEC_PARAM_TYPE_SET(t, i) (((uint32_t)(t) & 0xF) << ((i)*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.
prefer something like:
#define TEEC_PARAM_TYPE_SET(t, i) (((uint32_t)(t) & GENMASK(3, 0)) << \
((i) * 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.
Mm... I'd have to steal GENMASK
from the kernel, unless it's in some user-space header I'm not familiar with. I don't know if that'd be clearer.
Perhaps I can take 0xF
out and give it a name that describes why that number?
libteec/include/linux/tee.h
Outdated
#define TEE_IOCTL_SHM_DMA_BUF 0x2 /* dma-buf handle on shared memory */ | ||
#define TEE_IOCTL_SHM_MAPPED (1 << 0)/* memory mapped in normal world */ | ||
#define TEE_IOCTL_SHM_DMA_BUF (1 << 1)/* dma-buf handle on shared memory */ | ||
#define TEE_IOCTL_SHM_OCALL (1 << 2)/* memory used for an OCALL */ |
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 an output call */
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'd prefer keeping OCALL since that's what we call it.
@etienne-lms, thank you for the review. Regarding the renaming of The Perhaps With respect to replacing "OCALL" with "RPC", I'm not opposed. However, @jenswi-linaro had expressed a liking for the name "OCALL" in the issue we discussed this feature in last year. Additionally, OCALL, or "out call", is the term used by the Open Enclave SDK and Intel's SGX for the same feature, so I figured we could reuse it. Having said that, I'll go with whatever name you all coalesce on that fits within the readily established nomenclature. Lastly, as to your request for a cleaner patch set, I'll gladly readjust the commits to fit what you requested, though I'll wait until we've decided on the right names. |
Regarding, the |
Yes. I'm of two minds about adding this capability. On the one hand, it's possible that the version of OP-TEE that the client library is talking to does not support OCALLs. In this case, we fail right away if the CA expects OCALL support but OP-TEE does not provide it. On the other hand, we could do away with the capability, and just open the session. If the CA expects OCALL support, this means that the TA probably makes use of OCALLs. If OP-TEE was compiled without OCALL support, the TA will fail to make OCALLs, and that failure will presumably be reported back to the CA. So we have the choice between checking for OCALL support and failing right away before even opening the session, or not checking for OCALL support and letting the TA fail to send any later. I chose to be explicit and have OP-TEE report support, or lack thereof, for the feature. However, if we wish to not pile on another capability, it's possible to do without it. What do you think?
I've considered this, and I'm open to changing my mind. The way I conceptualize OCALLs is as a response to a function invocation. That is, one calls Additionally, a developer presumably controls both the CA and the TA. As such, when opening a session to a TA that is known to request OCALLs, it would make sense that the conduit for delivery is the session; OCALLs at the context level may be conceptualized as coming from any TA to which a session is opened via that context, regardless of whether all or only some of the TAs request OCALLs. Lastly, OCALLs must still be attached to sessions, at least technically. This is because on session close, all outstanding OCALLs must be cancelled. If one prematurely closes a session, say due to an error, we can't wait until the context is released to cancel pending OCALLs because the secure thread is stuck on an RPC. The flip-side to these arguments is an observation that Jens made whereby a TA may call another TA which itself sends an OCALL. Therefore, the CA might receive an OCALL from a TA other than the one the session was opened against. This is the reason I added the TA UUID parameter to the OCALL handler callback, which wasn't there in the first try at this feature. In light of this, it could make sense to have a catch-all OCALL handler in the CA for all possible TAs. Hence, if the handler must already support handling OCALLs from multiple TAs, it may as well handle OCALLs from all TAs opened against a context, at which point the handler may also as well be attached to the context. The counterargument to the previous argument is that a developer might still want to know which session an OCALL came from and decide what to do accordingly, especially if multiple sessions are opened on the same context against the same multi-instance TA: the handler will probably want to know which session the OCALL came from to distinguish between TA instances. This could be resolved by adding a session parameter to the OCALL handler callback (which I think I should add anyway). The problem with this approach is that the OCALL handler callback loses the ability to have a per-session callback context (the Thoughts? Lastly, Jens also mentioned that one is not allowed to call back into the TA from the OCALL handler, which is true, and I've added no way to detect this. I'll go ahead and implement a check to prevent re-entry. |
Adding my 2 (euro) cents to the discussion...
|
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.
Some initial comments
libteec/include/linux/tee.h
Outdated
#define TEE_IOCTL_SHM_DMA_BUF 0x2 /* dma-buf handle on shared memory */ | ||
#define TEE_IOCTL_SHM_MAPPED (1 << 0)/* memory mapped in normal world */ | ||
#define TEE_IOCTL_SHM_DMA_BUF (1 << 1)/* dma-buf handle on shared memory */ | ||
#define TEE_IOCTL_SHM_OCALL (1 << 2)/* memory used for an OCALL */ |
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'd prefer keeping OCALL since that's what we call it.
libteec/include/linux/tee.h
Outdated
@@ -63,6 +64,7 @@ | |||
* OP-TEE specific capabilities | |||
*/ | |||
#define TEE_OPTEE_CAP_TZ (1 << 0) | |||
#define TEE_OPTEE_CAP_OCALL (1 << 1)/* Supports calls from TA to CA */ |
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 this should be a generic capability instead, TEE_GEN_CAP_OCALL
. I suppose only OP-TEE will support it in the nearest future, but I see no reason why other TEEs shouldn't be able to reuse infrastructure.
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've turned it into a generic one, and is now handled as such in the library.
libteec/src/tee_client_api.c
Outdated
} | ||
} | ||
|
||
res = TEEC_OpenSession(ctx, session, destination, connection_method, |
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 means that OCALLs can't be done while the TA is initializing. It might not be a big problem, but it will be a bit annoying when documenting and perhaps lead to some special cases too.
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 has been addressed by attaching the OCALL handler to the context, as you've requested.
I prefer failing early, it's a bit more tidy in my mind. Registering OCALL handler in the context or the session? |
bf071e5
to
38cf78b
Compare
Design question: Currently, the PR has the TEE Client API pass shared memory to the CA that was allocated on request of the TA via the While this reflects the underlying fact that the shared memory in question can be used across multiple OCALLs (i.e., it's not a This is not how function invocations on TAs work: regardless of whether the underlying shared memory can persist across multiple invocations or is temporary, the TA function invocation handler gets a buffer and a size; no offset. The changes I'm working on would instead have the TEE Client API pass buffers to the CA's OCALL handler as I'm torn: on the one hand, using temporary reference semantics makes it easier to write OCALL handlers because offsets are not involved, and don't have to be, since What do you all think? P.S.: The Travis CI failure is about style complaints that I don't think are true issues. |
38cf78b
to
e275327
Compare
Checked during context initialization.
I've added the handler and a context-specific data pointer as a setting on |
I think there is only one warning type that we want to ignore here ("do not add new typedefs"), but all the others can be eliminated:
|
Ah, thanks for the pointers! Will do.
I'll happily do so, but the style won't match the rest of the file if I do. Parameters are indented with three tabs in the file, for example:
Preference? |
This P-R needs to be rebased. |
1b78c51
to
9713137
Compare
Done. On a separate note, I noticed warnings still about typedefs from Any ideas? |
The purpose of |
One minor thing re. commit "checkpatch: reverse sort typedefs.checkpatch", and although I have reviewed it already... I suggest the following additional change: diff --git a/typedefs.checkpatch b/typedefs.checkpatch
index 9b7906d..729ae36 100644
--- a/typedefs.checkpatch
+++ b/typedefs.checkpatch
@@ -69,9 +69,9 @@ CK_FLAGS
CK_DESTROYMUTEX
CK_DATE_PTR
CK_DATE
-CK_CREATEMUTEX
CK_C_INITIALIZE_ARGS_PTR
CK_C_INITIALIZE_ARGS
+CK_CREATEMUTEX
CK_CHAR_PTR
CK_CHAR
CK_CCM_PARAMS_PTR Indeed,
Note, this "C" ordering happens to be what I obtained in In any case there does not seem to be any impact on checkpatch -- the important thing is to have [1] As I said OP-TEE/optee_os#2685 (comment) and this is still true with |
9713137
to
547aaf8
Compare
Done.
Thank you for taking the time to explain this! |
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.
In the description for "libteec: implement OCALL support during function invocation":
- s/TEEC_InvokeFunction/TEEC_InvokeCommand()/
- It could be worth mentioning explicitly that the OCALL handler is executed in the context of the thread that called
TEEC_InvokeCommand()
(did I get this right? I think I did.)
Plus one minor thing below. With that:
Reviewed-by: Jerome Forissier <jerome@forissier.org>
public/tee_client_api.h
Outdated
* OCALLs. | ||
* | ||
* @param handler Pointer to the function to execute to handle an OCALL. | ||
* @param data Arbitrary pointer to pass to the OCALL handler function. |
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 refer to TEEC_OcallHandler()
argument ctxData
?
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. I've added comments indicating this.
* to. If name is set to NULL, the default TEE is connected | ||
* to. NULL is the only supported value in this version of | ||
* the API implementation. | ||
* @param context The context structure which is to be initialized. |
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.
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 actually made a mistake in the header declaration. Everywhere else the parameter is named context
, so I've changed ctx
to that.
public/tee_client_api_extensions.h
Outdated
@@ -50,6 +50,64 @@ TEEC_Result TEEC_RegisterSharedMemoryFileDescriptor(TEEC_Context *context, | |||
TEEC_SharedMemory *sharedMem, | |||
int fd); | |||
|
|||
/** | |||
* TEEC_InitializeContext2() - Initializes a context holding connection | |||
* information on the specific TEE, designated by the name string. |
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.
Maybe state that this function reflects standard TEEC_InitializeContext()
with 2 extra arguments to associate context data to the TEE context.
And same for TEEC_OpenSession2()
that implements standard TEEC_OpenSession()
with extra session data.
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.
Edited as requested.
libteec/src/tee_client_api.c
Outdated
uint32_t n; | ||
TEEC_Result res; | ||
|
||
if ((!settings && numSettings) || (settings && !numSettings)) |
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 (settings && !numSettings)
should be a valid case. If numSettings
is 0, no setting is registered with the TEE context and that's fine.
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.
Fixed.
libteec/src/tee_client_api.c
Outdated
if ((!settings && numSettings) || (settings && !numSettings)) | ||
return TEEC_ERROR_BAD_PARAMETERS; | ||
|
||
if (settings) { |
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: can remove if (settings)
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.
Removed.
libteec/src/tee_client_api.c
Outdated
@@ -51,12 +52,35 @@ | |||
/* How many device sequence numbers will be tried before giving up */ | |||
#define TEEC_MAX_DEV_SEQ 10 | |||
|
|||
/* No SHM flags */ | |||
#define TEE_IOCTL_SHM_NONE 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.
Should this be in libteec/include/linux/tee.h around line 46?
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.
Moved it there.
5ffb563
to
cfd36b0
Compare
Thank you @jforissier and @etienne-lms for your reviews, and my sincere apologies for the massive delay. I believe I've addressed your comments. As to Jérôme's comments on the commit description, I've edited it as requested (and you are indeed correct on the thread context comment.) I've foregone adding the |
cfd36b0
to
8472211
Compare
Hi @HernanGatta, it's good to hear from you again! 👍 😄 To be honest, I was afraid that you would have moved on to something else, which would have been unfortunate given the amount of work already done on this feature (especially on your side!). That being said, don't worry about the delay. We are not on a tight schedule, and contributions and reviews are always made on a best effort basis. It should be pretty clear to everyone, hopefully.
Thanks. I've double checked, it all looks good and well documented, so:
|
8472211
to
d3f1555
Compare
Thank you for your note. There's been a bit of a switcheroo regarding work and priorities but I'm not letting this go :)
Applied, thanks! |
Rearrange entries in typedefs.checkpatch in reverse alphabetical order. Signed-off-by: Hernan Gatta <hegatta@microsoft.com> Reviewed-by: Jerome Forissier <jerome@forissier.org>
A new flag is required to mark shared memory registered for OCALL usage. Signed-off-by: Hernan Gatta <hegatta@microsoft.com>
Enable detection of whether the TEE was built with OCALL support during context initialization. Signed-off-by: Hernan Gatta <hegatta@microsoft.com>
Add a new function, TEEC_InitializeContext2, that allows a developer to pass configuration parameters in the form of distinct settings. One of the new settings is for configuring OCALLs, where the caller sets a callback handler for when an OCALL arrives from a TA. Having multiple settings in this manner helps reduce the number of auxiliary functions necessary. Were new functionality to be added in the future, no new functions would need to be introduced. Instead, one would only require a new setting. Signed-off-by: Hernan Gatta <hegatta@microsoft.com>
Add a new function, TEEC_OpenSession2, that allows a developer to pass configuration parameters in the form of distinct settings. One of the new settings is for attaching an arbitrary pointer to the session. This is useful when an OCALL arrives from the TA and the handler requires contextual information to proceed that changes depending on which session the OCALL arrived through. Having multiple settings in this manner helps reduce the number of auxiliary functions necessary. Were new functionality to be added in the future, no new functions would need to be introduced. Instead, one would only require a new setting. Signed-off-by: Hernan Gatta <hegatta@microsoft.com>
OCALLs allow a TA to invoke functions on their CA with parameters, if desired, both during session open and command invoke. The flow begins when a CA calls TEEC_InvokeCommand. If the TEE context was initialized with the OCALL setting, libteec includes an additional parameter, the OCALL parameter, in the function invocation IOCTL. The presence of the OCALL parameter lets the kernel driver know that an OCALL may result from the invocation. If an OCALL does arrive from the TA, the OCALL parameter includes information about the OCALL, including the ID of the function that libteec must handle. These are: allocate shared memory, free shared memory, and invoke a function on the CA. If either of the first two functions arrives at libteec, the library handles these on behalf of the CA, allocating and freeing shared memory as necessary. When the third function arrives, libteec processes the OCALL's parameters. These will have temporarily replaced the parameters of the original function invocation. Additionally, the 'func' element of the IOCTL parameters will have been modified to carry the command ID that the TA requests that the CA execute on its behalf. The library passes this ID along with the parameters and arbitrary data pointers configured via the settings API to the CA-provided OCALL handler. After the handler is finished processing the request, libteec performs minor post-processing on the parameters and calls back into the driver to let it know that the OCALL has been handled. It is possible for a TA to invoke multiple OCALLs in the same originating function invocation. Additionally, the same mechanism detailed above applies to when a CA calls TEEC_OpenSession or TEEC_OpenSession2. That is, the TA may invoke one or more functions in sequence on its CA during session open. Lastly, the CA-provided OCALL handler is executed in the context of the thread that originally called TEEC_OpenSession, TEEC_OpenSession2, or TEEC_InvokeCommand. That is, when a TA invokes a function on its CA, these functions call into the CA-provided OCALL handler. Signed-off-by: Hernan Gatta <hegatta@microsoft.com> Reviewed-by: Jerome Forissier <jerome@forissier.org>
The addition of OCALL functionality breaks binary compatibility with existing applications by modifying the layout of certain structures. Section 3.1 of the GlobalPlatform TEE Client API specification does not mandate binary compatibility. As such, increase the version number for the library from 1.0.0 to 2.0.0. Signed-off-by: Hernan Gatta <hegatta@microsoft.com>
d3f1555
to
65e343a
Compare
Latest push is a rebase only. |
This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time. |
Overview
This PR implements OCALLs in the TEE Client API.
Related PRs: OP-TEE, Linux, OP-TEE Examples.
Session Open
A new function is added,
TEEC_OpenSessionEx
, whose signature is identical toTEEC_OpenSession
, but takes two additional parameters. The first is an array of typed settings, while the second provides the number of settings in the array.One such setting is the OCALL setting, which allows the developer to specify a callback for whenever an OCALL arrives, as well as an arbitrary context pointer.
The rationale behind using session settings is that it is conceivable that in the future, additional features are added that require configuration. Instead of creating new, independent functions to deal with those new features, a new setting type can be added and the existing API set remains the same. The Open Enclave SDK implements a similar pattern for its
oe_create_enclave
function.When the OCALL setting is specified in
TEEC_OpenSessionEx
, it checks that the underlying context reports that OP-TEE supports OCALLs. If so, it opens a session in the usual way viaTEEC_OpenSession
, then stores the OCALL configuration in the session object.Sample usage:
OCALL Handling
When OCALL support is configured, calls to
TEEC_InvokeFunction
are rerouted via the ECALL IOCTL instead of the INVOKE IOCTL. Around the IOCTL invocation, a loop exists to catch early returns, indicating that an OCALL request arrived. When that happens, the Client API takes care of dealing with shared memory allocation and free requests, as well as of parameter processing before and after dispatching an OCALL to the OCALL handler.Signed-off-by: hegatta@microsoft.com