Enclave

public abstract class Enclave

Subclass this inside your enclave to provide an entry point. The outside world communicates with the enclave via two mechanisms:

  1. Local connections from the host. But remember the host is malicious in the SGX threat model, so anything received from the host cannot be completely trusted. Override and implement receiveFromUntrustedHost to receive the byte arrays sent via com.r3.conclave.host.EnclaveHost.callEnclave.

  2. EnclaveMail, an encrypted, authenticated and padded asynchronous messaging scheme. Clients that obtain a EnclaveInstanceInfo from the host can create mails and send it to the host for delivery. Override and implement receiveMail to receive mail via the host.

Enclaves can sign things with a key that appears in the EnclaveInstanceInfo. This can be useful when the enclave is being used to create a proof of correct computation, rather than operate on secret data.

Please use the method onStartup to provide the configuration required to initialise the enclave, and the method onShutdown to release the resources held by the enclave before its destruction.

The enclave also provides a persistent key-value store (persistentMap) which is resistant to rollback attacks by the host. Use this to persist data that needs to exist across enclave restarts. Any data stored just in local variables will be reset on restart. The default file system can also be used both as a temporary scratchpad but also for persistence.

Constructors

Enclave
Link copied to clipboard
Enclave Enclave()

Methods

callUntrustedHost
Link copied to clipboard
byte[] callUntrustedHost(byte[] bytes)

Sends the given bytes to the callback provided to com.r3.conclave.host.EnclaveHost.callEnclave.

byte[] callUntrustedHost(byte[] bytes, Function<byte[], byte[]> callback)

Sends the given bytes to the callback provided to com.r3.conclave.host.EnclaveHost.callEnclave. If the host responds by doing another call back into the enclave rather than immediately returning from the callback, that call will be routed to callback. In this way a form of virtual stack can be built up between host and enclave as they call back and forth.

createAttestationQuote
Link copied to clipboard
@Beta()
byte[] createAttestationQuote(byte[] reportData)

Create a new attestation quote containing optional user specified report data.

getEnclaveInstanceInfo
Link copied to clipboard
EnclaveInstanceInfo getEnclaveInstanceInfo()

The serializable remote attestation object for this enclave instance.

getKdsEnclaveInstanceInfo
Link copied to clipboard
EnclaveInstanceInfo getKdsEnclaveInstanceInfo()

The remote attestation object for the KDS enclave this enclave is using for persistence. This will be null if this enclave is not configured to use a KDS.

getPersistentMap
Link copied to clipboard
Map<String, byte[]getPersistentMap()

Returns a persistent key-value store where string keys can be mapped to byte values. Use this MutableMap to securely store data that needs to be available across enclave restarts.

The entire map is serialised and encrypted after each receiveMail and receiveFromUntrustedHost call and is given to the host to persist. On restart the host is required to use the latest version of the map to re-initialise the enclave. Conclave makes a best-effort attempt at preventing the host from being able to rewind map, i.e. using an older version instead of the latest.

The persistent map is not enabled by default. This is done by setting the enablePersistentMap configuration in the enclave's build.gradle to true. The map is also not available if the enclave is multi-threaded (i.e. threadSafe is overridden to return true). Support for this maybe added in a future version.

Note, the keys are encoded using UTF-8 and the encoded size of each key cannot be more than 65535 bytes.

getSignatureKey
Link copied to clipboard
PublicKey getSignatureKey()

The public key used to sign data structures when signer is used.

getThreadSafe
Link copied to clipboard
boolean getThreadSafe()

If this property is false (the default) then a lock will be taken and the enclave will process mail and calls from the host serially. To build a multi-threaded enclave you must firstly, obviously, write thread safe code so the untrusted host cannot cause malicious data corruption by causing race conditions inside the enclave, and then override this method to make it return true. By doing so you signal that you're taking responsibility for your own thread safety.

onShutdown
Link copied to clipboard
void onShutdown()

Override this method to release any resources held by the enclave. This method is called when the enclave is asked to be shut down. This gives an opportunity to the enclave to release its resources before being destroyed.

onStartup
Link copied to clipboard
void onStartup()

Override this method if the enclave requires extra configuration. Please be aware that any initialization code must be placed in this method and not in the class constructor to ensure the enclave is started correctly. This method is invoked as the last step of the enclave initialization.

Any exceptions thrown by this method propagate out to the host wrapped in a EnclaveStartException. This occurs even in release mode, so care must be taken to avoid leaking any sensitive information in the exception message or stacktrace.

postMail
Link copied to clipboard
void postMail(byte[] encryptedMail, String routingHint)

The provided mail will be encrypted, authenticated and passed to the host for delivery.

Where the mail gets delivered depends on the host logic: in some applications the public key may be sufficient, in others, the enclave may need or want to provide additional direction using the routingHint parameter.

Note that posting mail is transactional. The delivery will only actually take place once the current enclave call or receiveMail call is finished. All posts (along with the enclave's sealed state that is automatically generated) take place atomically.

postOffice
Link copied to clipboard
EnclavePostOffice postOffice(EnclaveInstanceInfo enclaveInstanceInfo)

Returns a post office for mail targeted to an enclave with the topic "default". The target enclave can be one running on this host or on another machine. The post office is setup with the enclave's private encryption key so the recipient can be sure mail did indeed originate from this enclave.

The enclave will cache post offices so that the same instance is used for the same EnclaveInstanceInfo and topic. This ensures mail is sequenced correctly.

The recipient should use PostOffice.decryptMail to make sure it verifies this enclave as the sender of the mail.

EnclavePostOffice postOffice(EnclaveMail mail)

Returns a post office for responding back to the sender of the given mail. The mail's topic is used and the authenticated sender as the destination public key.

EnclavePostOffice postOffice(PublicKey destinationPublicKey)

Returns a post office for mail targeted at the given destination key, and having the topic "default". The post office is setup with the enclave's private encryption key so the recipient can be sure mail originated from this enclave.

The enclave will cache post offices so that the same instance is used for the same public key and topic. This ensures mail is sequenced correctly.

The recipient should use PostOffice.decryptMail to make sure it verifies this enclave as the sender of the mail.

If the destination is an enclave then use the overload which takes in an EnclaveInstanceInfo instead.

EnclavePostOffice postOffice(EnclaveInstanceInfo enclaveInstanceInfo, String topic)

Returns a post office for mail targeted to an enclave with the given topic. The target enclave can be one running on this host or on another machine. The post office is setup with the enclave's private encryption key so the recipient can be sure mail originated from this enclave.

The enclave will cache post offices so that the same instance is used for the same EnclaveInstanceInfo and topic. This ensures mail is sequenced correctly.

The recipient should use PostOffice.decryptMail to make sure it verifies this enclave as the sender of the mail.

EnclavePostOffice postOffice(PublicKey destinationPublicKey, String topic)

Returns a post office for mail targeted at the given destination key, and having the given topic. The post office is setup with the enclave's private encryption key so the receipient can be sure mail originated from this enclave.

The enclave will cache post offices so that the same instance is used for the same public key and topic. This ensures mail is sequenced correctly.

The recipient should use PostOffice.decryptMail to make sure it verifies this enclave as the sender of the mail.

If the destination is an enclave then use the overload which takes in an EnclaveInstanceInfo instead.

receiveFromUntrustedHost
Link copied to clipboard
byte[] receiveFromUntrustedHost(byte[] bytes)

Override this method to receive bytes from the untrusted host via com.r3.conclave.host.EnclaveHost.callEnclave.

Default implementation throws UnsupportedOperationException so you should not perform a supercall.

Any uncaught exceptions thrown by this method propagate to the calling com.r3.conclave.host.EnclaveHost.callEnclave. In Java, checked exceptions can be made to propagate by rethrowing them in an unchecked one.

receiveMail
Link copied to clipboard
void receiveMail(EnclaveMail mail, String routingHint)

Invoked when a mail has been delivered by the host (via com.r3.conclave.host.EnclaveHost.deliverMail), successfully decrypted and authenticated (so the EnclaveMail.authenticatedSender property is reliable).

Default implementation throws UnsupportedOperationException so you should not perform a supercall.

Any uncaught exceptions thrown by this method propagate to the calling com.r3.conclave.host.EnclaveHost.deliverMail. In Java, checked exceptions can be made to propagate by rethrowing them in an unchecked one.

signer
Link copied to clipboard
Signature signer()

Returns a Signature object pre-initialised with the private key corresponding to the signatureKey, ready for creation of digital signatures over data you provide. The private key is not directly exposed to avoid accidental mis-use (e.g. for encryption).

When serialising your signed data structure, consider also attaching the serialised EnclaveInstanceInfo of this enclave with it (enclaveInstanceInfo). This ensures the signature can still be verified by the end-user even if the enclave's signing key changes.

Properties

enclaveInstanceInfo
Link copied to clipboard
private EnclaveInstanceInfo enclaveInstanceInfo

The serializable remote attestation object for this enclave instance.

kdsEnclaveInstanceInfo
Link copied to clipboard
private EnclaveInstanceInfo kdsEnclaveInstanceInfo

The remote attestation object for the KDS enclave this enclave is using for persistence. This will be null if this enclave is not configured to use a KDS.

persistentMap
Link copied to clipboard
private Map<String, byte[]persistentMap

Returns a persistent key-value store where string keys can be mapped to byte values. Use this MutableMap to securely store data that needs to be available across enclave restarts.

The entire map is serialised and encrypted after each receiveMail and receiveFromUntrustedHost call and is given to the host to persist. On restart the host is required to use the latest version of the map to re-initialise the enclave. Conclave makes a best-effort attempt at preventing the host from being able to rewind map, i.e. using an older version instead of the latest.

The persistent map is not enabled by default. This is done by setting the enablePersistentMap configuration in the enclave's build.gradle to true. The map is also not available if the enclave is multi-threaded (i.e. threadSafe is overridden to return true). Support for this maybe added in a future version.

Note, the keys are encoded using UTF-8 and the encoded size of each key cannot be more than 65535 bytes.

signatureKey
Link copied to clipboard
private PublicKey signatureKey

The public key used to sign data structures when signer is used.

threadSafe
Link copied to clipboard
private boolean threadSafe

If this property is false (the default) then a lock will be taken and the enclave will process mail and calls from the host serially. To build a multi-threaded enclave you must firstly, obviously, write thread safe code so the untrusted host cannot cause malicious data corruption by causing race conditions inside the enclave, and then override this method to make it return true. By doing so you signal that you're taking responsibility for your own thread safety.