Typical workflow:
Code layout:
It’s simple because Teaclave codebase provides us with proc_macro that generates an implementation of struct for us.
#[teaclave_service(
teaclave_authentication_serivce, // Name
TeaclaveAuthenticationApi // Trait
TeaclaveAuthenticationError // ErrorType
)]
#[derive(Clone]
pub(crate) struct TeaclaveAuthenticationApiService {
db_client: DbClient,
jwt_secret: Vec<u8>,
}
Then you implement the trait for this service struct. APIs are defined in the protobuf DSL:
service TeaclaveAuthenticationApiService {
rpc UserRegister(UserRegisterRequest) returns (UserRegisterResponse);
rpc UserLogin(UserLoginRequest) returns (UserLoginResponse);
}
The Rust struct definitions are automatically generated using prost. Since each service is a standalone enclave, we can actually start the enclave using an untrusted app interface. A common practice looks like:
fn start_enclave_serivce(tee: Arc<TeeBinder>, config: RuntimeConfig) {
let input = StartServiceInput::new(config);
let command = ECallCommand::StartService;
// Note: this is an ECALL interface.
match tee.invoke::<StartServiceInput,
TeeServiceResult<StartServiceOutput>>(command, input) { ... }
unsafe { libc::raise(signal_hook::SIGTERM) }
}
fn main() -> anyhow::Result<()> {
let tee = Arc::new(TeeBinder::new(PACKAGE_NAME).context("...")?);
let config = teaclave_config::RuntimeConfig::from_toml("runtime.config.toml").context("...")?;
let tee_ref = tee.clone();
// Then we spawn a new thread.
std::thread::spawn(move || {
start_serivce(tee_ref, config);
});
}
Ecalls are marked with #[handle_ecall]
procedural macro, and commands are defined using macro:
register_ecall_handler!(
type EcallCommand,
(ECallCommand::StartService, InputType, OutputType),
);
Basically we need to use docker images to properly set up all the necessary services and environment. The documentation on the website seems to be outdated, and one should follow the instructions under docker
directory. The docker container used to build the Teaclave can be launched by the following command, assuming docker and SGX SDK are properly installed.