Package com.r3.conclave.client

Types

EnclaveClient
Link copied to clipboard
public class EnclaveClient implements Closeable

Represents a client of an enclave. EnclaveClient manages the encryption of requests that need to be sent to an enclave (sendMail), and using an EnclaveTransport, transports encrypted mail to the host for delivery to the enclave. It also provides a polling mechanism with pollMail for retrieving any asychronous responses from the enclave.

Creating a new client instance requires providing an EnclaveConstraint object. This acts as an identity of the enclave and is used to check that the client is communicating with the intended one. A private encryption key is also required. There is an constructor overload which creates a random new one for you, or you can use Curve25519PrivateKey.random to create a new random one yourself.

After creating a new client, users will need to call start and provide an EnclaveTransport for communicating with the host. Which implemenation of EnclaveTransport is used will depend on the network transport between the client and host. If the host is using the conclave-web-host server then users can use com.r3.conclave.client.web.WebEnclaveTransport for the transport.

Sending and receiving Mail

After starting the client is able to send mail to the enclave using sendMail. EnclaveClient will encrypt the body and optional envelope with the private encryption key and then pass the encrypted bytes onto the provided EnclaveTransport to deliver it to the host. sendMail can optionally return back a decrypted EnclaveMail which is the synchronous response from the enclave, if it produced one.

For receiving asychronous responses, i.e. those which the enclave produces for the client but which are produced due to other clients, pollMail will return the next asynchronous response if one is available.

Thread safety

EnclaveClient is not thread-safe. sendMail and pollMail must be called from the same thread. If the client wants to poll for asychronous mail in a background thread then that same thread must also be used for sending mail. A simple way to achieve this is to use a single-threaded ScheduledExecutorService. The following (incomplete) code sample shows how this might be done.

    ScheduledExecutorService singleThreadWorker = Executors.newSingleThreadScheduledExecutor();
BlockingQueue<EnclaveMail> receivedMail = new LinkedBlockingQueue<>();

private ScheduledFuture<?> pollingTask;

void start() throws InvalidEnclaveException, IOException {
enclaveClient.start(enclaveTransport);
pollingTask = singleThreadWorker.scheduleAtFixedRate(() -> {
try {
EnclaveMail mail = enclaveClient.pollMail();
if (mail != null) {
receivedMail.add(mail);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}, 0, 5, TimeUnit.SECONDS); // Poll every 5 seconds
}

Future<EnclaveMail> sendMail(byte[] body) {
return singleThreadWorker.submit(() -> enclaveClient.sendMail(body));
}

void close() throws IOException {
if (pollTask != null)
pollingTask.cancel(true);
enclaveClient.close();
}

Enclave rollback

One key security feature EnclaveClient provides is detection of rollback attacks by the host on the enclave. This type of attack is where the host restarts the enclave but in an older state. The enclave itself is unable to detect this but it can leverage its clients so that they may detect it. However not all clients may detect the rollback, but at least some will.

Detection is enabled by default in EnclaveClient. However it's only detected when the client next receives mail which is why sendMail and pollMail can throw EnclaveRollbackException. What action needs to be taken depends on the client's security policy but it may include contacting other clients (if any are known) or maybe even the enclave host if there is genuine foul play and they can be brought to account. It's also important to note a rollback can arise from a genuine mistake if the host accidently restarted the enclave from an old state.

The client can continue to be used to send and receive mail after an EnclaveRollbackException is thrown. However the state of the client and the state of the enclave are probably now out of sync and further communication with the enclave may be unsafe. If rollback attacks are not a concern at all then detection for it can be turned off completely by overriding ignoreEnclaveRollback to return true. The same security caveats apply.

Restarts

EnclaveClient is designed to handle both enclave and client restarts. If the enclave restarts then its encryption key changes but EnclaveClient will automatically switch to the new encryption key when it detects this. Notifications for restarts can be enabled by overriding onEnclaveRestarted. This might be needed if the enclave is non-persistent and the client needs to re-submit their data. It could also be used as an indication of a rollback attack.

To support client restarts the state of EnclaveClient must be persisted and then restored. Failing to do this will prevent the client from sending or receive mail due to spurious errors. To this end, save can be used to serialize the state of the client which can be restored using the EnclaveClient constructor that takes in a byte array. This is provided solely as a convenience and the state of the client can be persisted any other way. See the save documentation for more details.

PostOffice

EnclaveClient is an extension to PostOffice and provides features it cannot support. If these features are not needed and you simply need to send a one-off mail, for example, then use EnclaveInstanceInfo.createPostOffice to create a post office for encrypting requests and decrypting any responses.

EnclaveRollbackException
Link copied to clipboard
public class EnclaveRollbackException extends RuntimeException

Exception that's thrown by EnclaveClient if it detects the enclave's state has been rolled back.

EnclaveTransport
Link copied to clipboard
public interface EnclaveTransport

Represents a transport layer between the client and enclave host. EnclaveTransport defines how a host needs to behave to be able to support EnclaveClient objects that connect to it. It is responsible for transporting encrypted bytes between the host and client, whilst EnclaveClient deals with the encryption and decryption and retry attempts if the enclave is restarted.

Details such as how to start and shutdown the transport are implementation specific.

The Conclave SDK provides com.r3.conclave.client.web.WebEnclaveTransport as an implementation for connecting the client to a host which is using the conclave-web-host.