How persistence works in Conclave applications
Conclave 1.2 is here! It brings with it a load of important features, an important one being the Enclave Persistent Filesystem and the Persistent Map.
Conclave is a confidential computing platform used to develop solutions that pool and process confidential data from multiple parties. This computation can be used to provide a high level of insight and analysis. Conclave builds on a trusted execution environment called an enclave. An enclave is a trusted region in memory to which the CPU blocks access. No other entity – such as the operating system or the computer provider – has access to the data within this trusted region. The enclave process runs separately within the host but access is restricted to the host or the client.
Enclaves have limited access to the outside world in order to keep them isolated from the rest of the server hardware. Inside an enclave, you don’t get access to components like filesystems, networks, and others normally found within an operating system. However, there could be cases where your application will require some way to retain state data – to allow storing of important data that is not lost during enclave restarts. In other words, you need a way to persist information from your enclave. A simple way to achieve this is to provide persistence using a filesystem.
Conclave 1.1 implemented an in-memory Java filesystem so developers could download Java libraries that would work inside the enclave. Version 1.1 stored the entire filesystem within the enclave memory. Such a filesystem provides a good assurance of data privacy as all files are stored in encrypted enclave memory. Developers can use standard Java file input/output to work with these files. However, as it is an in-memory filesystem, the contents will be lost if the enclave is restarted or stopped.
Conclave 1.2 combats this limitation with the support of a persistent filesystem. This filesystem is encrypted by the enclave and is stored by the host in non-volatile storage, such as the disk of the host. From a developer standpoint, this is no different from using in-memory file storage, with the only difference being that the data gets persisted through the encrypted storage on the host. You can use the persisted filesystem to read and write files that need to be available after a restart of your enclaves. This is represented as a single encrypted file on the host; your enclave will load/save/read/write all files and directories into that file. The encryption is done using a key only known to the enclave, thus ensuring strong data confidentiality. When the enclave restarts and the filesystem file is present, Conclave will try to load and prepare the filesystem file so that it can be used by the enclave.
Enabling a persistent filesystem in your Conclave application
To enable a persistent filesystem in your Conclave application:
- Enable the persistentFileSystemSize in the enclave runtime environment in build.gradle. This is the setting to specify the maximum size of the persisted filesystem. The default size for it is 0m – indicating that the persisted filesystem is disabled. The size can be specified in bytes, but can also be specified in kilobytes, megabytes, or gigabytes by inputting k, m, or g respectively after the value. It is important to note that this value cannot change once the enclave has started for the first time. So it is important to choose an appropriate value that is big enough for your long-term needs.
inMemoryFileSystemSize = "0"
persistentFileSystemSize = "64m"
If required, you can also specify the max size of the in-memory filesystem as well. You have the option to enable both types of filesystems or just one of them. In case you choose to have both the filesystems available, the persisted filesystem will be mapped to the / directory and the directory /tmp will be reserved for the in-memory filesystem. All files and directories that you write into /tmp directory will be considered temporary. All the other locations will be used to persist your files. In the case where either the in-memory or the persisted filesystem is chosen, the filesystem of your choice will be mounted to the / directory and you can write your files and directory wherever you want.
- Specify the path to the encrypted filesystem file in your EnclaveHost.start.
enclaveHost.start(AttestationParameters.DCAP(), null, Paths.get("/home/USER/conclave.disk");
If you are using the host web server, add your file to the arguments under “filesystem.file.”
- Your enclave code could now use the persisted filesystem inside to perform Java file input/output operations within the enclave.
Note that the enclaves cannot access the disc directly, so it must rely on the host to provide the persistence. However, the host is untrusted and is considered to be a part of the attack surface for the enclave. Any requests made by the enclave to the host can give out information about access patterns of data which could potentially be used by the host to gain unwarranted information and insights. In response to this potential vulnerability, Conclave takes measures to ensure the data is not only encrypted but access patterns of data are also hidden from the host. Thus, Conclave does not only just encrypt the data but also hides any patterns within it that might give some clues as to what the enclave is doing. Each block of data is encrypted using AES GCM encryption. This ensures that the blocks are tamper-resistant and each block is unique. The order of these blocks is randomized inside the enclave before calling out the host to persist this data.
The enclave may still be susceptible to replay and side-channel attacks occurring when the host observes the frequency of read/write actions to/from the file. Note that while the persisted filesystem is encrypted and unreadable by the host, this is not a transactional system when used alone and there would be no protection if the host performed a rollback attack. As mentioned in the last paragraph – the enclave relies on the host to store the encrypted filesystem file. So, here the host has complete control over which filesystem file version it provides to the enclave. A malicious host may give back an older block of the file to the enclave. As for the enclave, it cannot detect an older version as it doesn’t have access to a trusted time source or a secure monotonic counter. Thus, the enclave cannot check if it has been given an older copy of the filesystem.
An alternate way to persist information in Conclave is the persistent map. The persistent map is a persistent, encrypted key-value store that is hardened against rollback attacks. The enclave can use this key-value store to persist information as required.
Enabling the persistent map has potential performance implications – as the enclave must encrypt the map every time it processes a new mail from the client. In addition, it adds an extra burden on the client (although the Enclave Client in 1.2 could help with this). Therefore, one must evaluate the tradeoffs before making a design decision. One may also use the persistent map along with the persistent filesystem to provide better security.
- To enable the persistent map, enable the same in the enclave’s build.gradle. Set the enablePersistentMap to true (the default is false) and specify the maxPersistentMapSize (the default is 16m).
enablePersistentMap = true
maxPersistentMapSize = "16m"
You could now use the persistent map within your Enclave. A sample showing the use of persistent map and persistent filesystem can be found here.
Want to learn more?
Below are some helpful resources to learn more about Conclave and Confidential Computing.