A deep dive into Conclave 1.0
Another day, another vulnerability, another hack. Losing control of critical personal data feels random and inevitable (here’s one very recent example).
It’d be great if we could trust IT service providers, but we can’t. Even if they’re totally respectable pillars of society who have only the best intentions, the difficulty of keeping networks secure means their good will isn’t enough.
The computer industry has spent many years researching solutions. One of them is confidential computing (formerly known as trusted computing). Software running on a server can prove its identity over the internet via what’s called a remote attestation. The attestation contains the hash of the program, the fact that it’s been tamper-proofed by the hardware and an encryption key. Software outside the so-called enclave cannot get in to access its secrets, devices outside the CPU are blocked by transparent memory encryption, and clients can communicate with the enclave using the key.
It’s a simple concept yet with it you can solve many problems that previously required intractably slow or complex cryptography:
- Any computation that combines data from multiple parties and doesn’t want a trusted intermediary.
- Proving to users how a software-as-a-service actually operates, so the privacy policy stops being just a bunch of words and becomes a hard guarantee.
- Building decentralised services from peer-to-peer networks of untrusted nodes.
- Blocking attacks on your servers by keeping the data the attackers want inside an enclave whilst pushing as much software as possible to the outside.
Only one problem: the idea is simple yet using it is hard.
Enter …. 🥁 …. Conclave 1.0.
But first, let’s briefly talk about how to design enclaves the right way.
The Zen Of Enclaves
As of January 2021 the best implementation of confidential computing is Intel SGX. It follows the UNIX philosophy of small programs, each doing one task well. An enclave is meant to be as small as possible and meant to do only one thing — computation on some data. Everything else should be kept outside the enclave: network handling, database management, monitoring, metrics, administration … all of it.
Some approaches to confidential computing don’t do this, and attempt to run an entire operating system and serving stack inside the enclave. This isn’t useless, but it’s also not really maximising the benefits of the concept. There are two problems with it:
- Putting a vulnerable software stack inside a protected memory space doesn’t make it secure. Enclaves erect a hard border between software components so malicious or hacked software on one side can’t get into the other, but that’s no use if the software the enclave is protecting is itself vulnerable. One way to minimise vulnerabilities is to just minimise the amount of code in the protected space that’s handling attacker-controlled data.
- Remote attestation is a fundamental part of the concept. Users check what’s running before they upload their data. But, attestations just give you a SHA2 hash. To know what it means someone must audit the software that hashes to that value, and check that it really does what it claims to do. If your software stack changes every day the hash will change every day too so how can your users — or external auditors — possibly keep up?
Reflecting on the zen of enclaves we reach the following conclusions:
- An enclave is a protected sub-module of your wider application, not an entire application or serving stack by itself.
- An enclave is only core business logic that your users care about.
- An enclave is a security weak point: coding errors inside the enclave render the protection useless.
Therefore plumbing — stuff that’s neither here nor there from your users perspective— that stuff should be kept outside the enclave. Upgrades to it won’t change the hash reported to clients and thus won’t imply any additional audit work. The enclave itself should be written with tools that help us avoid coding errors.
Enter Conclave
Conclave is a simple API that lets you take a module of your app and run it inside an enclave. It uses GraalVM, so supports any language that can run on Graal. Languages we’ve tested include Java, JavaScript and Kotlin, but also possible are R, Python, Ruby, C, C++, FORTRAN, Rust, Clojure and more. You apply a plugin for the Gradle build system. Then you structure your app to pass messages in and out of that module, instead of doing function calls.
A JVM is an excellent tool for writing enclaves because of its emphasis on combining performance and safety. Garbage collected and type safe code is provably free of memory management errors, which are still one of the most common ways software gets hacked. In Conclave we use the GraalVM Native Image JVM, which produces self-contained binaries with minimal memory usage.
There are always 3 components in any enclave-oriented application:
- The client
- The host
- The enclave
You can learn more about how these pieces interact in this article on Conclave’s architecture.
Conclave provides a client library that can be used to send and receive messages from the enclave. It works a little differently to how other enclave APIs do, so you can read about the justifications here and here.
Writing a simple apps is straightforward. Follow the hello world tutorial to learn the additional steps required: mostly, this means configuring the build system and then checking the server-side code from the client using the Conclave API.
Conclave 1.0
Today we launched the first stable version of Conclave. It’s been in beta for a while, and during that time we’ve done usability studies on the API to ensure it’s understandable and flexible. It’s free for individuals and early-stage startups who open source their code, and pricing for everybody else starts low and grows only as your solution itself gains adoption. In other words it’s free to experiment and learn. The documentation is available here.
This new release adds to beta 4 the following enhancements:
- A better API for mail.
- Padding for mails to ensure that message sizes can’t act as a side channel. Different padding policies are provided: you can pick between a fixed min size, max seen so far, a moving average or a custom policy.
- The
java.nio.file
API is now connected to an in-memory file system. This enhances compatibility with libraries that expect to load data or configuration from files, whilst avoiding the complexities of running a full filesystem engine inside the enclave. For persistence use the mail-to-self pattern. - A new script is provided to run Gradle inside a Linux container, on macOS. This can simplify running tests against a fully compiled enclave (i.e. not using mock mode).
- Enclaves are now locked by default, i.e. multi-threaded enclaves are now opt-in rather than opt-out. This ensures a malicious host can’t multi-thread an enclave that’s not thread-safe.
- GraalVM has been upgraded to 20.3, improving performance and compatibility. An upgrade to 21.0 will come soon which will add support for Java object serialisation.
- Various usability enhancements, bug fixes, and other safer defaults.