Fortanix EDP architecture
With the Fortanix EDP, you write your enclave like you would any other
application, starting with a main
function:
1
2
3
fn main() {
println!("Hello, world!");
}
The EDP provides all the necessary abstractions and interfaces to launch the
enclave and take the output from the enclave and send it to the OS. In this
case, that means taking the string Hello, world!
and printing it to the
terminal. This simple example showcases the power of the different components
of the EDP, shown in this diagram:
The usercall interface (see below) is implemented inside the enclave directly
in Rust's standard library. This means you can use most of the primitives
you're used to, such as collections and networking. The small changes to
support enclaves are explained in Using Rust's std
.
Outside the enclave, the enclave-runner
crate takes care of loading the
enclave. Once the enclave is loaded, it provides a shim layer between the
usercalls coming from the enclave, and the system calls needed to talk to the
outside world. ftxsgx-runner
is an executable based on enclave-runner
which
should be suitable for most enclave applications. However, you can easily
implement your own runner using the enclave-runner
crate.
Service architecture
EDP applications should be thought of as providing a service to other parts of your system. An EDP application might interact with other services which themselves might be EDP applications. The service may be implemented as a gRPC server, an HTTPS server with REST APIs, or any other service protocol.
To ensure that a client can verify it's talking to a legitimate enclave service, it's imperative that the client set up a secure channel directly with the enclave, and that it authenticate the server using remote attestation. Both the establishment of the secure channel and the authentication can be provided by TLS. See the examples chapter on how to run a TLS server inside the enclave.
Usercall interface
Just like a normal OS, the Fortanix EDP defines an API and ABI that
applications use to interact with the environment. Just like most Linux
programmers will never call the syscall
function, EDP programmers will
generally not need to dive into the specifics of usercalls.
The usercall API has been specifically designed for use with SGX and consists of less than 20 calls. Common patterns such as buffer-passing are implemented consistently across all the calls. The interface is kept small intentionally to aid security audits.
The interface has been specifically designed to avoid known attacks on enclave interfaces, such as Iago attacks and information leakage through structure padding. In addition, the Rust type system is used to disallow direct access to user memory from the enclave and avoid TOCTTOU issues.