Enclaves cannot directly access OS-provided services. Instead, an enclave must do an OCall to an interface routine in the untrusted application. While calling outside adds a performance overhead, there is no loss of confidentiality. However, communication with the OS requires the release of data or the import of non-secret data, which needs to be handled properly.
Even though OCalls might be necessary sometimes, they are calls outside the enclave and therefore have associated some security risks.
- Enclave operations that require an OCall, such as thread synchronization and I/O, are exposed to the untrusted domain. An enclave must be designed in such a way that it prevents leaking side-channel information that would allow an attacker, who is looking at the untrusted functions called from an enclave, to gain insight into enclave secrets, see Section Protection from Side-Channel Attacks for additional information.
- An enclave must be prepared to handle the scenario where the OCall function is not performed at all. The return value from an OCall, which is an enclave input, comes from the untrusted domain and must not be relied upon. It might appear that an OCall has been successfully completed when it has not. For instance, an attacker might drop an enclave’s request to write sealed data to disk and tell the enclave the file was written successfully.
- An enclave cannot depend on nested ECalls occurring in certain order during an OCall. A developer may limit the ECalls that are allowed during a given OCall, since the state information (corresponding to the OCall in progress) can be stored inside the enclave. However, once an enclave makes an OCall there is no guarantee the untrusted domain will not recursively call into the enclave, and the enclave has no control over the order in which nested ECalls occur or the actual ISV interface functions invoked.
When an ISV function inside the enclave invokes an OCall:
- The OCall only exposes the OCall function arguments (including the referenced data) and the return value to the untrusted domain.
- When the OCall returns, the return value and any marshaled data of the pass-by-reference output parameters are inside the trusted environment (thus not accessible to an attacker) and the input-only function arguments (including the referenced data) are not changed. When the return value is a pointer, only the reference will be inside the trusted environment. The enclave software must check the data buffer referenced by the returned pointer like any other reference passed into the enclave.
- When the OCall returns, the trusted thread context is the same as before the OCall was made, except for the volatile registers and the output data on the trusted stack.
In certain scenarios, the enclave writer may avoid OCall functions by repartitioning the application and passing the information that an OCall is meant to obtain as an input parameter to an ISV interface function.