← all posts
2026-07-10 5 min read by Alekos Filini

How we solved rollback attacks

In the last blog post I described broadly the problems Enclavia solves to make enclaves secure, easy and accessible to anybody. I briefly mentioned that one of our solutions is a secure encrypted storage for enclaves, with anti-rollback protection. In this article we’ll go over what that means and why it’s so crucial for achieving high security with enclaves.

What’s a rollback attack?

Before we get started, let’s discuss what a rollback attack is and why it is dangerous.

A secure enclave can be pictured as a secure bubble inside a CPU. Its memory is encrypted in such a way that even the host machine, its operator, or anybody compromising them can’t peek into it. Enclaves also provide an attestation of which exact code they are running inside.

These two primitives give users confidence that their data is not accessible by the provider (thanks to memory encryption), and that it’s managed properly (thanks to the attestation).

However, enclaves lack any form of long term storage: data can be kept in memory, but in case of a system failure, reboot or even a maintenance upgrade, it would be lost.

Enclavia solves this problem by giving enclaves a storage volume. Its data is encrypted inside the enclave, and only unreadable ciphertext is ever sent to our storage server, outside. We are not the first to come up with this solution, and although its implementation can be tricky, it’s a relatively known pattern used in the industry.

This poses another problem though: users trust the enclave because of its attestation, but by definition they don’t trust the host or the operator, which can’t provide one and could misbehave. By encrypting data within the enclave we make sure the untrusted outside world can never read the plaintext, but there’s another potential attack the host could mount: a rollback attack.

After a reboot, the enclave will ask the host for the last snapshot of its encrypted storage. During this crucial step, unless further protections are implemented, it has to trust the host that the ciphertext it received is the latest version. Again, the host can’t directly read or modify data because it doesn’t know the encryption key. But it could send an older snapshot causing a rollback.

Animation: an enclave writes encrypted snapshots v1, v2, v3 to an untrusted host. After a reboot it asks for the latest snapshot and the host returns the stale v2, which decrypts and authenticates correctly.
fig. 1 · the host can't read the snapshots, but it picks which one to return

Why is it dangerous?

Whether a rollback is an attack vector for a certain protocol depends on the specific mechanic of the protocol. But generally speaking, if your enclave relies and makes decisions on any sort of persistent state (which is why they would need storage in the first place) being able to rollback the storage would, at minimum, cause the enclave to misbehave.

Imagine for example that you want to enforce a maximum number of failed login attempts before locking down a user account: this number of attempts would be saved in the encrypted storage, so that it wouldn’t be lost in case of a reboot. The host, being able to rollback the storage, could “wind back” the counter after a few failed attempts, effectively bypassing the limit.

Animation: a snapshot holds a failed-login counter at 3 of 5. After a reboot the host rolls storage back, the counter winds to 0 and the account lock flips open: the attempt limit is bypassed.
fig. 2 · roll back the counter, and a 5-attempt limit becomes infinite attempts

In the bitcoin ecosystem, the security of many protocols, especially layer-twos like statechains, relies on the service provider to behave honestly and delete sensitive key material that could allow itself or hackers to double spend user funds.

Introducing an enclave reduces the trust assumption in the service provider, because instead of purely promising to delete the key it can now prove it does through the attestation. But rollback attacks would be able to undo the deletion, making the setup less secure.

How we solved it

Our solution relies on a simple intuition: the storage system running outside your enclave cannot be trusted because it can’t provide an attestation proving its behavior. While it promises to never rollback any storage, it can’t be proven cryptographically and so you and your customers would have to take our word for it. But who said it couldn’t run in an enclave?

Let’s assume we could run the whole Enclavia storage infrastructure within an enclave: our system would be able to provide an attestation to your enclave, proving its behavior and thus guaranteeing its honesty. Your enclave wouldn’t have to take the host’s word for it, it would be able to cryptographically verify it is not misbehaving.

This sounds promising, but it quickly results in a recursive problem: if your enclaves rely on another enclave for their storage, what would the storage system enclave rely on?

So this might seem like a dead end, unless we also challenge the assumption that we need persistent storage in the first place. That might be counter intuitive: we just said that enclaves need storage so that they can survive reboots. But here’s the idea: there are other ways to prevent data loss in case of reboots, for example by using a cluster of replicated nodes.

Enter the synchronizer

This is in essence the design of our synchronizer, which is used to establish a precise timing sequence for every storage write. The synchronizer doesn’t keep the encrypted data itself, but just enough metadata to ensure any modifications across the filesystem can be detected. Whenever a write happens in your enclave, the untrusted host updates the encrypted data, while the synchronizer updates the metadata.

After reboot your enclave fetches data both from the host and the synchronizer, and compares the two. If they diverged, it will refuse to boot.

Animation: the enclave writes an encrypted blob to the host and a tiny merkle root to a three-node synchronizer across three availability zones. After a reboot it recomputes the root from the blob and compares: matching roots boot verified, a stale blob diverges and the enclave refuses to boot.
fig. 3 · bulk ciphertext on the untrusted host, a few bytes of truth on the synchronizer

To provide redundancy, the synchronizer is not one single instance, it’s a mesh of enclaves, spread across different AWS Availability Zones. They use a simple consensus mechanism named Raft to ensure they all agree on the set of metadata of your enclave. And most importantly, they attest to each other and only allow a peer to connect if the PCR set matches perfectly, meaning a node will only speak to other nodes running its exact same version of the code.

With the synchronizer in place, your enclave never has to take the host’s word for anything. It fetches its data, checks it against an attested mesh that only ever moves forward, and refuses to boot the moment the two disagree. Freshness stops being a promise and becomes something you can verify.

Alekos
CEO, Head of Engineering @ Enclavia

← all posts questions? hello@enclavia.io

Inert by design.
Attested by silicon.

We're onboarding early teams now.

Ready to start building? talk to us

or leave your email. We'll reach out when it's your turn