Getting to “Hello” with Conclave

Conclave Jul 19 2021 By: David Awad
Comments

0 Comments

Views

222 Views

Getting to Hello with Conclave
David Awad
David Awad Developer
Share this post:
Copied

Curious about using a secure enclave? This is the right place to be. Conclave is a tool for deploying production-ready, secure enclaves that you can use on SGX-enabled virtual machines in Azure or other cloud providers. 

When you consider that enclaves allow you to develop and agree on a specific piece of code that you can share with other parties, knowing that the code can’t be tampered with, the value proposition starts to be clear. These are bold claims, so let’s quantify them first. 

How can you possibly have complete trust in code running on someone else’s machine? The key idea behind the secure enclave is remote attestation. When you agree with another party that you’re going to run a particular piece of software within a secure enclave that they’re hosting, you’ll get together and create a hash of the final version of the code, which you will use as a unique key to verify the software that’s running. The remote attestation then combines that hash with a key from Intel to give you confidence that the host is running the code you expect. This is aside from all of the standard built-in features of the SGX enclave

Let’s start with the flow of data at the highest level. We’ll want to keep in mind that Conclave works using three crucial abstractions: clients, hosts, and enclaves. It’s just like any other client-server architecture you may have come across from the web development world. The client is the entity that connects to the enclave maintained by the host. It’s as simple as that.

Conclave architecture diagram

Clients

The clients work by connecting directly to the enclave:

  1. We check that the enclave is running precisely the code that we expect using the membership attestation.
  2. We send encrypted messages to the enclave specifying the program within the enclave that we want to run. In this case, the “reverse” program. 
  3. The enclave eventually responds with the result of our computation.
    
// This is the client that will upload secrets to the enclave for processing.

// In this simple hello world app, we just connect to a TCP socket, take the EnclaveInstanceInfo we're sent
// and transmit an encrypted string. The enclave will reverse it and send it back. You can use this sample
// as a basis for your own apps.

// assume we've gotten our args from outside this code
String toReverse = String.join(" ", args);

// Connect to the host, it will send us a remote attestation (EnclaveInstanceInfo).
DataInputStream fromHost;
DataOutputStream toHost;

while (true) {
    try {
        // assume our host program is also running on localhost 
        System.out.println("Attempting to connect to localhost:9999");
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), 9999), 5000);
        fromHost = new DataInputStream(socket.getInputStream());
        toHost = new DataOutputStream(socket.getOutputStream());
        break;
    } catch (Exception e) {
        System.err.println("Retrying: " + e.getMessage());
        Thread.sleep(2000);
    }
}

byte[] attestationBytes = new byte[fromHost.readInt()];
fromHost.readFully(attestationBytes);
EnclaveInstanceInfo attestation = EnclaveInstanceInfo.deserialize(attestationBytes);

// Check it's the enclave we expect. This will throw InvalidEnclaveException if not valid.
System.out.println("Connected to " + attestation);
// Two distinct signing key hashes can be accepted.
// Release mode: 360585776942A4E8A6BD70743E7C114A81F9E901BF90371D27D55A241C738AD9
// Debug mode:   4924CA3A9C8241A3C0AA1A24A407AA86401D2B79FA9FF84932DA798A942166D4
EnclaveConstraint.parse("S:360585776942A4E8A6BD70743E7C114A81F9E901BF90371D27D55A241C738AD9 "
        + "S:4924CA3A9C8241A3C0AA1A24A407AA86401D2B79FA9FF84932DA798A942166D4 PROD:1 SEC:INSECURE").check(attestation);

// Now we checked the enclave's identity and are satisfied it's the enclave from this project, we can send mail
// to it.
PrivateKey myKey = Curve25519PrivateKey.random();

// For encrypting mail to the enclave we need to create a PostOffice from the enclave's attestation object.
// The post office will manage sequence numbers for us if we send more than one mail, which allows the enclave
// to check that no mail has been dropped or reordered by the host.
//
// We use a topic value of "reverse" but any will do in this example. However, mail related to each other and
// which need to be ordered must use their own topic. Topics are scoped to the sender key and so multiple clients
// can use the same topic without overlapping with each other.
//
// In this example it doesn't matter as we only send one mail with a random key, but in general it is very
// important to use the same post office instance when encrypting mail with the same topic and private key.
PostOffice postOffice = attestation.createPostOffice(myKey, "reverse");

byte[] encryptedMail = postOffice.encryptMail(toReverse.getBytes(StandardCharsets.UTF_8));

System.out.println("Sending the encrypted mail to the host.");

toHost.writeInt(encryptedMail.length);
toHost.write(encryptedMail);

// Enclave will mail us back.
byte[] encryptedReply = new byte[fromHost.readInt()];
System.out.println("Reading reply mail of length " + encryptedReply.length + " bytes.");
fromHost.readFully(encryptedReply);
// The same post office will decrypt the response.
EnclaveMail reply = postOffice.decryptMail(encryptedReply);
System.out.println("Enclave reversed '" + toReverse + "' and gave us the answer '" + new String(reply.getBodyAsBytes()) + "'");

toHost.close();
fromHost.close();

    

There are additional comments in this example to clarify, but there’s certainly not much code. This example is everything the client would need to be able to connect to the enclave. 

Hosts

On the other side, the host maintains an enclave. This is the same as you’d expect from a typical client-server architecture. 

That means that the host: 

  • Allocates a port to listen for inbound connections.
  • Boots the enclave. 
  • Reads encrypted input to and from the enclave to clients. 

So let’s see what this looks like in context on the host. 

    
// set up server for clients to reach enclave
int port = 9999;
System.out.println("Listening on port " + port + ". Use the client app to send strings for reversal.");
ServerSocket acceptor = new ServerSocket(port);
Socket connection = acceptor.accept();

// Just send the attestation straight to whoever connects. It's signed so that is MITM-safe.
DataOutputStream output = new DataOutputStream(connection.getOutputStream());

// load our enclave app
EnclaveHost enclave = EnclaveHost.load("com.r3.conclave.sample.enclave.ReverseEnclave");

// start the enclave
enclave.start(new AttestationParameters.DCAP(), (commands) -> {
    for (MailCommand command : commands) {
        if (command instanceof MailCommand.PostMail) {
            try {
                sendArray(output, ((MailCommand.PostMail) command).getEncryptedBytes());
            } catch (IOException e) {
                System.err.println("Failed to send reply to client.");
                e.printStackTrace();
            }
        }
    }
});


// The attestation data must be provided to the client of the enclave, via whatever mechanism you like.
final EnclaveInstanceInfo attestation = enclave.getEnclaveInstanceInfo();
final byte[] attestationBytes = attestation.serialize();

// Now let's send a local message from host to enclave, asking it to reverse a string.
final Charset utf8 = StandardCharsets.UTF_8;
System.out.println("Reversing Hello World!: " + new String(enclave.callEnclave("Hello World!".getBytes(utf8)), utf8));

sendArray(output, attestationBytes);

// Now read some mail from the client.
DataInputStream input = new DataInputStream(connection.getInputStream());
byte[] mailBytes = new byte[input.readInt()];
input.readFully(mailBytes);

// Deliver it. The enclave will give us the encrypted reply in the callback we provided above, which
// will then send the reply to the client.
enclave.deliverMail(1, mailBytes, "routingHint");

// Closing the output stream closes the connection.
output.close();
enclave.close();

    

Once again, there aren’t many surprises, and the code is relatively short. The client-server architecture is the same as any other web architecture you may have used. It’s only the fact that we’re using an enclave that makes things a little bit different. 

Enclave

The enclave is where the magic happens. This is a secure computing environment guaranteed by the hardware and verified with encryption. 

What happens in the enclave? It will consume some data and produce an output. Here’s a rough outline of the process. The enclave: 

  1. Receives data in encrypted messages. 
  2. Processes the data. 
  3. Returns an encrypted output to the client.
    
/**
 * Simply reverses the bytes that are passed in.
 */
public class ReverseEnclave extends Enclave {
    // We store the previous result to showcase that the enclave internals can be examined in a mock test.
    byte[] previousResult;

    @Override
    protected byte[] receiveFromUntrustedHost(byte[] bytes) {
        // This is used for host->enclave calls so we don't have to think about authentication.
        final String input = new String(bytes);
        byte[] result = reverse(input).getBytes();
        previousResult = result;
        return result;
    }

    private static String reverse(String input) {
        StringBuilder builder = new StringBuilder(input.length());
        for (int i = input.length() - 1; i >= 0; i--)
            builder.append(input.charAt(i));
        return builder.toString();
    }

    @Override
    protected void receiveMail(long id, EnclaveMail mail, String routingHint) {
        // This is used when the host delivers a message from the client.
        // First, decode mail body as a String.
        final String stringToReverse = new String(mail.getBodyAsBytes());
        // Reverse it and re-encode to UTF-8 to send back.
        final byte[] reversedEncodedString = reverse(stringToReverse).getBytes();
        // Get the post office object for responding back to this mail and use it to encrypt our response.
        final byte[] responseBytes = postOffice(mail).encryptMail(reversedEncodedString);
        postMail(responseBytes, routingHint);
    }
}

    

You’ll notice the enclave abstraction defines two methods to be filled out by the developer (that’s you). These are two different ways of doing the same thing. One reverses our hello world string when receiving information from the host, and the other is for receiving generic mail from an external client.

`receiveFromUntrustedHost`

This method does what it sounds like it does. It receives mail from the outside world that it doesn’t trust, namely from the host. It then performs the same reverse procedure of the hello world string and returns it back. 

`receiveMail`

A quick look at the method signature shows us this method is designed to receive mail from the outside world, process it, and end with a call to postMail with the result of the processing to return the data outside the enclave. 

If all of this made sense to you, I think you’ll have a strong start in using Conclave as a tool for secure computation. There are all kinds of use cases, like confidential machine learning, private database querying, and even storing your private keys securely from the host operating system! 

Enclaves are one of the many new tools that the software community has in its arsenal for pushing the bounds of what we can accomplish with the software. I look forward to seeing what you build!

David Awad
David Awad David Awad is a Developer Evangelist at R3, an enterprise blockchain software firm working with a global ecosystem of more than 350 participants across multiple industries from both the private and public sectors to develop on Corda, its open-source blockchain platform, and Corda Enterprise, a commercial version of Corda for enterprise usage. Follow David on Twitter here.

Leave a Reply

Subscribe to our newsletter to stay up to date on the latest developer news, tools, and articles.