RELIANT - Deniable encryption for Qubes OS

Many users have been requesting plausible deniability in Qubes in some form, either for the installation as a whole or specific qubes. RELIANT is a project that provides multi-level plausible deniability in Qubes via Shufflecake, a modern deniable encryption system.

  • dom0 is made live/volatile via intrinsic systemd functionality.
  • Deniable qubes are stored in Shufflecake volumes.
  • During boot you enter the standard LUKS password for dom0, and the Shufflecake password for the top volume you want to decrypt.
  • RELIANT facilitates this through initramfs and userspace tooling.

We emphasize the importance of preventing and avoiding leakage of any information, direct or indirect, about the hidden volumes and qubes within. This is largely addressed by moving dom0 to RAM, supported by hash verification of non-volatile storage media. But there are side channels we cannot address, such as traffic analysis or eavesdropping. For more information, see the README.

The project is in a highly experimental state and uses several features not officially supported by QubesOS, and I do not have the time or resources to maintain a fork. However, subject to the developers’ approval, I can start working on patches that will bring the necessary functionality into core Qubes codebase.

If anyone is interested in testing the system, I would be happy to provide support if you contact me. I have tested it myself and it does work, but as a developer I will inevitably be biased, especially regarding usability and convenience.

Q: How to update dom0 or templates?

A: There is a Maintenance Mode which can be entered by erasing systemd.volatile=overlay from the GRUB command line.

Q: Does volatile dom0 require lots of RAM?

A: Not really - most devices which can run Qubes, can run RELIANT as well.

Q: How to copy files between qubes?

A: Never copy directly between hidden qubes in different Shufflecake volumes - this will reveal the source qube’s existence and name to the target. Use a proxy disposable qube.

Q: What are the prerequisites for installation?

A: Enough free space on disk for the Shufflecake partition, a bootstrap qube with Docker, good knowledge of Linux and Qubes for troubleshooting.

11 Likes

Hell yeah. This sounds fuckin’ awesome, I look forward to trying it out.

1 Like

It would be amazing to implement this in Qubes. Besides shufflecake hidden volumes, a volatile dom0 is also a good idea.

2 Likes

The codeberg readme mentions how there’s no ram wipe. Recently, a RAM wipe script posted to the forum. It also includes two live modes which may improve security. Are you considering adding this script to RELIANT in the future?

1 Like

Indeed, I have seen that topic. Regarding the RAM wipe, I will have to look into it. Our main concern is kernel-space memory, which contains the dm-sflc module with all the encryption and volume information. At a glance, I do not see any mention of kexec, which would be necessary for such an operation. The script posted by the OP just does

echo 3 > /proc/sys/vm/drop_caches

which is IMO insufficient for full cold boot attack protection.

However, in the related GitHub issue, adrelanos says

ram-wipe relies on the operating system during shutdown to shutdown all processes, VMs, umount all disks, etc. ram-wipe then runs its first pass at the end of the shutdown process to fill up all RAM which will hopefully overwrite everything of importance. ram-wipe will then kexec into the same kernel with a special kernel parameter to make sure even the old kernel gets wiped from RAM and does another pass of RAM wiping.

which would imply there is indeed a kexec in the process. Therefore, it is possible to do a proper RAM wipe, including kernel-space. When adding the functionality to RELIANT, I’d prefer the full solution. It also should be noted that there are several security issues with the RAM wipe approach,

  • An attacker could just hard reset the device,
  • On some devices, the proper shutdown sequence may take a while,

which was also brought up in the issue thread,

Can’t the attacker hard reset the system, and bypass any protection that rely on the system going through a controlled shutdown sequence?

Yes. So for ram-wipe or any alternative to be useful, it needs to be triggered. Potential triggers are A) shutdown; B) device removal; or C) a panic key.

In this case there are two modes of attack, attended and unattended. Attended is simple - unplug the panic key, device is shut down and RAM is erased. I would also highly advise physical security measures, such as tape or epoxy, to be applied to the device. For unattended mode, the situation is much more difficult. Do we need to include some kind of tamper detection? Of course, the best practice is to never leave your device unattended and turned on, but this could literally happen in a matter of minutes.

I’d be interested to hear yours and other users’ thoughts on the matter since that is something I intend to address at some point. In any case, the conclusion is that, despite being an imperfect solution, the RAM wipe would be a net positive for security and therefore should be included after I review all the relevant code.

For the live modes they present, I won’t be so sure, because they mention

The size of the dom0 memory must exceed the amount of space used on the dom0 disk! Otherwise live modes won’t start. The size of dom0 changes after each update; kernel updates can significantly increase the dom0 size on disk, and live modes may stop working after a kernel update.

I don’t think this is correct, since an OverlayFS-based live mode only stores deltas and does not need to copy the entire disk into RAM. Regardless, I suspect that our implementation of the live mode would have a lower RAM footprint than the alternatives thanks to certain patches we apply to the Qubes storage pool management code. It has been verified to function on a machine with 16 GB of total RAM and 4 GB of RAM allocated to dom0.

Despite this, there are some issues with it since SystemD, which we use to create the tmpfs, unmounts it by default, leaving it permanently with the default size of 1 GB. This can work, but barely. RELIANT_PROFILING solves this, but relies on patching the relevant SystemD binary, which is undesirable. Therefore, in the future we’ll have to move to custom overlay creation code. For the same reason, I am hesitant to include any third-party modules as-is, since we may need to make heavy modifications for our usecase, and at this point it could be better to write our own.

1 Like