The Fortanix SGX ABI (compiler target
x86_64-fortanix-unknown-sgx) is an
interface for Intel SGX enclaves. It is a small yet functional interface
suitable for writing larger enclaves. In contrast to other enclave
interfaces, this interface is primarly designed for running entire
applications in an enclave.
The Fortanix SGX ABI specification consists of two parts:
- The calling convention (see FORTANIX-SGX-ABI.md)
- The execution environment and usercalls (this document)
Whereas the calling convention describes how information is passed to and from the enclave, this document ascribes meaning to those values.
The execution environment and usercalls have been designed with the following goals in mind:
- Compatible with most Rust code: Rust code that doesn't link to other C libraries and that doesn't use files (see no. 5) should compile out of the box.
- Designed for SGX: The SGX environment is unique and not compatible with other application environments out there. The primitives specified in this document are designed to work well with SGX, not to be similar to or compatible with primitives known from other environments.
- Designed for network services: The most interesting usecase for SGX is to run applications remotely in an untrusted environment, e.g. the cloud. Therefore, there is a primary focus on supporting functionality needed in those situations.
- No filesystem: Encrypted filesystems are hard. Especially in SGX, consistency and freshness are big concerns. In this initial version, there is no filesystem support, which is fine for most network services, which would want to keep their state with a database service anyway. Support might be added in the future.
- Not POSIX: The POSIX API is huge and contains many elements that are not directly supported by the SGX instruction set, such as fork and mmap. It is explicitly a non-goal of this specification to support all of POSIX.
- Designed to be portable: Enclaves don't interact directly with the OS, so there should be no need to recompile an enclave when running it with a different OS. This specification does not require any particular primitives or behavior from the OS.
Like on regular operating systems, there are two types of enclaves:
executable-type and library-type. The main difference between the two
different types is how the enclave may be entered. Once an enclave TCS is
entered, the different types act virtually identically. More information on
the two different types, TCSs, and enclave entry may be found in the
Once an enclave TCS is entered, it may performs synchronous usercalls as
described in the calling convention. The TCS maintains its execution state
between doing a usercall and returning from the usercall. Only when the TCS
exits, either through a non-usercall exit or through the
exit usercall, is the TCS state
destroyed. This is depicted in the following diagram.
Enclaves may also perform asynchronous usercalls. This is detailed in the
async module. Most usercalls can be submitted either
synchronously or asynchronously.
Asynchronous usercall specification.
Specification of TCS and entry function requirements.
An arbitrary-sized buffer of bytes in userspace, allocated by userspace.
The list of all usercalls.
Error code definitions and space allocation.
An event that will be triggered by userspace when the return queue is not or no longer empty.
An event that enclaves can use for synchronization.
An event that will be triggered by userspace when the usercall queue is not or no longer full.
Standard error file descriptor. This is not a secure output channel.
Standard input file descriptor. Input read this way is not secure.
Standard output file descriptor. This is not a secure output channel.
A value indicating that the operation was succesful.
Usercall numbers with this bit set will never be defined by this specification.
A file descriptor.
The first return value of usercalls that might fail.
The absolute address of a TCS in the current enclave.