Status  Version  License  Docs researchpaper  Website  Issue tracker  Mastodon  XMPP  Please don't upload to GitHub

Shufflecake - Full C Implementation - v0.5.6

Shufflecake is a plausible deniability (hidden storage) layer for Linux. You can consider Shufflecake a spiritual successor of tools like TrueCrypt and VeraCrypt, but vastly improved, both in terms of security and functionality. Official website: https://www.shufflecake.net.

This repository contains C source code and documentation to use and manage Shufflecake volumes.

WARNING: Shufflecake is a strong encryption and plausible deniability solution. The mere presence of Shufflecake on your device might put you at risk of being targeted, accused of crime or foul play, arrested, or worse. In Shufflecake there is no easy way to convince an adversary that you have given up all your passwords. Please consider carefully your threat model before using Shufflecake. In any case, this is still experimental software, please do not rely on its security or stability.

Overview

In the context of Shufflecake, a device, or cake, is the underlying raw block device (e.g., a disk) that is formatted to contain hidden data, while a volume, or layer, is the logical, encrypted and hidden "partition" within a device. The device can be a whole USB stick (or disk), a physical or logical partition, a file-backed loop device, etc. (you likely find it under /dev).

The three operating principles of Shufflecake are:

  • 1 device = multiple (concurrently usable) volumes;
  • 1 volume = 1 password = 1 "secrecy level";
  • unlocking a volume also unlocks all those of lesser secrecy level.

Volumes are password-protected, and embedded in the underlying device as data slices which are indistinguishable from random noise without the proper password. A Shufflecake-initialized device does not have cleartext headers, and is indistinguishable from random noise when not decrypted.

Up to 15 ordered Shufflecake volumes can be created on a single device, with the implicit assumption that "lower-order" volumes (e.g. layer 0) are less secret than "higher-order" ones (e.g. layer 3). Shufflecake is designed in such a way that it chains volumes in a backwards-linked list: volume i "points to" (contains the key of) volume i-1. This way, providing the key of volume i allows this tool to traverse the list and also automatically open volumes 0 through i-1 (besides volume i).

Opened volumes appear as block devices of the form sflc_X_Y in /dev/mapper and they can be used concurrently. It is up to the user to format them with an appropriate filesystem and mounting them before use. It is recommended to always unlock the most sensitive volume for daily use ("home alone" scenario), even if that volume is not being used or even mounted. Only open a subset of volumes (with a "decoy password") if under coercion. This is due to the high possibility of corrupting hidden volumes otherwise.

For security and consistency reasons, you cannot init/open/close nested volumes within the same device one at a time; this tool only allows to perform these operations on a chain of volumes in a device.

Installation

This implementation of Shufflecake consists of two components: a module for the Linux kernel (dm-sflc), and a shufflecake userland tool. Both are necessary in order to use Shufflecake. They have been tested on Linux kernel versions 6.1 (LTS), 6.8, and 6.17. The following instructions are given for Debian/Ubuntu and similar derivatives.

First of all, you need the kernel headers, device-mapper userspace library, and libgcrypt to compile the source. Use:

sudo apt install linux-headers-$(uname -r) libdevmapper-dev libgcrypt-dev

Important: you have to make sure to install an up-to-date version of libgcrypt that supports the Argon2id KDF algorithm. You need the 1.10.1 or later version, which might not be available in your local repositories (for example, Ubuntu 22.04 LTS), in which case you should find a workaround (either install manually or override your repositories by pinning an up-to-date package). You can check your current version (on Debian/Ubuntu) with:

dpkg -l libgcrypt20

Also, make sure that the Kconfig options CONFIG_CRYPTO_DRBG_HASH (and possibly CONFIG_CRYPTO_DRBG_CTR) are enabled, as they are not default options in the kernel's defconfig, although they are enabled by default on many distributions such as Debian and Ubuntu.

After that, just run make inside the Shufflecake source code directory. All the compilation artifacts will go in the respective subdirectories, and a copy of the kernel module dm_sflc.ko and the userland tool shufflecake will appear in the current directory. You can clean (delete) all these artifacts with make clean.

For now there is no make install option, if you want you can install Shufflecake system-wide manually, by moving the executable to the appropriate directory (e.g. /usr/bin) and making sure that the kernel module is loaded automatically at boot.

Tests

Tests are provided to check pre-install consistency. Run sudo make test to compile and run all the checks (sudo is requires to load a kernel module and perform block device operations, although local disk partitions are not touched, all tests are done using file-backed loop devices), or just make test to only check the cryptography layer. You can also run test scripts in a standalone way from the tests directory. Remember to make clean afterwards.

Benchmarks

A complete benchmark suite is provided in the benchmark-suite directory, to test the performance of Shufflecake on a given system and against other tools such as LUKS and VeraCrypt. Please refer to the documentation in that directory for instructions on how to run the benchmark scripts.

Usage

The shufflecake tool requires the dm-sflc kernel module to be already loaded. Therefore, first of all you must load the kernel module (and its dependency dm_mod if not already loaded) with:

sudo modprobe dm_mod
sudo insmod dm-sflc.ko

(Note: if you have Secure Boot enabled, this step might fail. See this section for workarounds.)

At this point you can run the shufflecake command as sudo shufflecake <action> <block_device>.

When finished, you can unload the module with

sudo rmmod dm_sflc

You can only do this if no Shufflecake volume is currently open. Notice the spelling difference between dm-sflc.ko (the module file) and dm_sflc (the module name given by the kernel). This is standard practice.

Initializing Device

sudo shufflecake init <block_device>

This command creates N volume headers on the given device, each of them sealed by the respective provided password, by properly formatting and encrypting the first N volume header slots. The number of desired volumes N and the related N passwords will be interactively asked at prompt. Alternatively, you can pass N by command line with:

sudo shufflecake --num-volumes=N init <block_device>

WARNING: With this operation you will lose any data stored in the device. Also, adding more volumes after initialization is not yet supported.

This command does not open the volumes (it does not create the virtual devices under /dev/mapper/), it only overwrites the device with randomness and formats the encrypted headers.

Opening Volumes

sudo shufflecake open <block_device>

A password will be required. If this is the password for volume M, then this command will open the first M volumes on the device. These will appear as virtual devices under /dev/mapper/, named sflc_<devID>_0 through sflc_<devID>_<M-1>, where devID is a Shufflecake-unique numeric ID assigned by the kernel module to the block device.

Notice that initially all these volumes will be unformatted; in order to use them to store files, once created for the first time you must format them with an appropriate filesystem, for example with:

sudo mkfs.ext4 /dev/mapper/sflc_X_Y

Also notice that Shufflecake does not auto-mount the volumes, you have to do it manually in order to see and manipulate their content, for example with:

sudo mount /dev/mapper/sflc_X_Y /media/yourusername/yoursflcsecretdrive

Closing Volumes

sudo shufflecake close <block_device>

Closes all the currently open volumes on a device, removing them from /dev/mapper/.

The command only asks for the block device name, i.e., it will close all volumes provided by that device at once, by first forcing a write on disk of any pending changes. However, in order to avoid any risk of data loss, it is always advisable to first umount any mounted open volume, for example with:

sudo umount /media/yourusername/yoursflcsecretdrive

Other Commands

The following commands implement additional useful features.

Changing a Password

sudo shufflecake changepwd <block_device>

A password will be required. If this is the correct password for a volume within that device, then the user will be prompted to enter a new password for that volume. Shufflecake will only modify a single ciphertext field in the header of that volume, without need of re-encrypting the volume itself.

Check if a Password is Correct

sudo shufflecake testpwd <block_device>

A password will be required. If this is the correct password for volume M, then this information will be returned to the user, without actually opening the volume. This can be useful if a user wants to be sure that a password unlocks a certain volume without risk of the OS logging the access to that volume and without the risk of corrupting the content of other, unlocked, hidden volumes.

Modes of Operation

Shufflecake can operate in two different modes, with different features in terms of security, performance, and data resilience.

Shufflecake Lite

As of v0.5.0, Shufflecake's default mode of operation is the "Lite" scheme. This mode introduces the AES-XTS encryption mode rather than AES-CTR, with a related change of header format. This mode has advantages compared to the old "Legacy" scheme: it offers the same level of security, but with better performance and data resilience, and it is therefore the strongly recommended way to use Shufflecake. It will be used by default whenever a Shufflecake command is invoked.

Scheme of Shufflecake Lite device layout

Shufflecake Legacy

For backward compatibility reasons, this release of Shufflecake still offers support for the old (pre-v0.5.x) "Legacy" scheme, which can be selected with the --legacy option when invoking init or open, all other actions (including close) do not require specifying a Shufflecake mode. This scheme uses AES-CTR with explicit IVs written on disks, and it offers therefore ciphertext re-randomization, which is in turn a necessary ingredient for achieving future modes with better security. However, since these modes have not yet been implemented, currently the use of Shufflecake Legacy has drawbacks and no advantages compared to other modes: it does not offer better security, while being slower, less space-efficient, and more prone to data corruption. The use of this mode is therefore discouraged, and will be deprecated at some point in the future. However, you must use this option when trying to open volumes created with an old (pre-v0.5.x) release of Shufflecake. You are strongly recommended to migrate Legacy volumes to the new Lite ones if you haven't done it yet.

Scheme of Shufflecake Legacy device layout

Shufflecake Full

This is a planned, but not yet implemented future mode of Shufflecake, which extends the old Legacy scheme with additional security and data resiliency features. The aim is to have a mode of operation which is equivalent to Shufflecake Lite in terms of data resiliency, but with better security albeit possibly worse performance.

Advanced Usage

This section documents advanced use cases and features of Shufflecake.

Recovering Unused Slices

Once a new slice is assigned to a Shufflecake volume, that assignment is static: that slice stays in the position map of that volume even if all its content (i.e. the files in the filesystem area mapped onto the slice) is deleted. On the long run, this can lead to a situation where there are no free available slices left for Shufflecake volume allocation, even if the filesystems of the volumes show plenty of available virtual space. In order to avoid this, Shufflecake implements slice garbage collection on close: all slices that only contain sectors unused by the filesystem on top are marked as free and removed from the slice mapping.

Usually, filesystems do not mark unused sectors automatically. To force this, call fstrim inside the filesystems of the open volumes, and then close the underlying device. Once the device is opened again, those slices will be newly available for allocation. This should be done every once in a while, especially after deleting large amount of data from the volumes.

Enabling R/W Workqueues

According to benchmarks, workqueue processing of READ and WRITE requests decreases I/O performances for most typical workloads, at least on SSDs. Since this is a very common situation on laptops nowadays, Shufflecake disables R/W workqueues by default. However, some WRITE workloads might actually enjoy a speed-up with workqueues. Moreover, workqueues might improve performance on HDDs (although this is untested).

Read and write queues can be optionally enabled on shufflecake open with the options --use-read-queue and --use-write-queue, respectively.

Volume Corruption Mitigation

As explained in the Shufflecake website's FAQ, if not all hidden volumes are opened and the user writes data to decoy volumes, there is a risk of data loss on the unopened hidden volumes (so-called "volume corruption"). This is because Shufflecake will try to allocate new slices for the decoy volumes by picking positions at random across all the (unopened) available space. There is ongoing research to mitigate this risk by using some form of redundancy on the volumes, basically by using error-correcting codes that can self-heal from a certain degree of corruption by sacrificing some disk space. In the meantime, users can resort to a "poor man's implementation" of this idea by using RAID redundancy on a partitioned hidden volume. This is still quite "hacky", and at the very minimum should be automated with some scripting.

More in detail:

  1. Open all Shufflecake volumes on a device, e.g. sflc_0_0 and sflc_0_1 in the case of two volumes (one decoy and one hidden).

  2. Partition the volume you want to protect (say, sflc_0_1) into different partitions using, e.g., fdisk or parted. Let's say you obtain 3 equal-sized partitions named sflc_0_11, sflc_0_12 and sflc_0_13.

  3. Use mdadm to build a redundant RAID array on these volumes. For example, if using RAID-1, you should use:

sudo mdadm --create --verbose /dev/md0 --level=1 --raid-devices=3 /dev/mapper/sflc_0_11 /dev/mapper/sflc_0_12 /dev/mapper/sflc_0_13

You can verify the creation of the RAID array with:

cat /proc/mdstat

WARNING: do not save the current RAID configuration to /etc/mdadm/mdadm.conf, otherwise it will super-obviously break plausible deniability.

  1. Format /dev/md0 with a filesystem of your choice, mount it, and use it.

  2. After umounting it, remember to disassemble the RAID device before doing shufflecake close.

You can use different redundant RAID systems such as RAID-5 (minimum 3 volumes) or RAID-6 (minimum 4 volumes, recommended 5 or more), each of them with different tradeoffs in terms of space wasted, speed, and corruption resilience. In any case there is no 100% guarantee that unopened hidden volumes will not be corrupted when writing data on decoys, so the recommended course of action for the user is still to open all devices for daily use (but mounting them is not mandatory). This method is intended to offer a certain degree of convenience for the user when recovering data in a hidden volume after an adversarial investigation, i.e., having some chance of recovering "gracefully" instead of having to restore from a backup.

Providing Passwords Non-Interactively

By default shufflecake init will ask the user for the number of volumes to create and the sequence of passwords. The number of volumes can be passed as argument with the -n option, but there is currently no built-in mechanism to provide passwords non-interactively, which might be useful, e.g., for scripting. However, there is a simple workaround. As an example with 3 volumes:

echo -e "password1\npassword2\npassword3" | sudo ./shufflecake -n 3 init <block_device>

If you don't want cleartext passwords to be logged in the shell history, you can put password0 ... password2 as the first three lines in a textfile, say passwords.txt, and pass them with:

sudo ./shufflecake -n 3 init <block_device> < passwords.txt

Both methods works with the init and open action, and we do not have current plans to change this behavior for the near future.

Using with Secure Boot

If you have Secure Boot enabled, then your kernel will most likely refuse to load an unsigned kernel module, such as dm-sflc.ko. You can confirm that that is the case if insmod dm-sflc.ko returns an error like "Key was rejected by service" (the kernel logs in dmesg might have more information). The only two solutions are:

  1. You (temporarily) disable Secure Boot.

  2. You enroll your own MOK (machine-owner key) and sign the kernel module dm-sflc.ko with it; you may need to recompile before signing.

Both these options have security implications, of course, which you should be aware of. We cannot provide a step-by-step guide for option 2, because the procedure is distro-specific. However, enrolling a MOK is a relatively standard operation, that is well supported by many distributions, so online guides should be easy to find.

Contribute

You are welcome to contribute to the Shufflecake Project with suggestions, code, and more. Please see the file CONTRIBUTING.md for guidelines on how do that effectively.

Developer Guide

A developer guide is available in the docs directory. The linked pages therein gather some documentation around non-trivial design and implementation choices.

Changelog

See the file CHANGELOG.md for a detailed history of changes.

[0.5.6] - 2025-11-24

  • Added proper test units on make test.
  • Added developer guide.
  • Implemented proper handling of FLUSH requests and FUA-flagged bio's.
  • Introduced handling of arbitrary size I/O requests

[0.5.5] - 2025-09-24

  • Experimental fix for the issue of bad memory allocation on some archs due to the improper use of vmalloc.
  • Added instructions on how to deal with unsigned kernel modules with Secure Boot on.

[0.5.4] - 2025-09-06

  • Working garbage collection of unused slices.
  • Workqueue processing of READ and WRITE requests made optional by default.
  • Fixed benchmark scripts.

[0.5.3] - 2025-07-05

  • Fixed GCC compilation error.
  • Added support to FLUSH for Shufflecake Lite and made position maps write-back.

[0.5.2] - 2025-01-17

  • Progress status during init.
  • Added CONTRIBUTING.md.
  • Fixed make test not working due to misnamed constants and variables.

[0.5.1] - 2024-10-13

  • Reorganized interface between dispatcher and dm-legacy through pointers to functions.
  • Fixed debug error message when reading unallocated slices on dm-legacy.

[0.5.0] - 2024-09-01

  • BREAKING CHANGE: major rewrite, bugfixes, introduced Shufflecake "Lite" as a default mode of operation.

Bugs

Bugs and other issues are tracked at https://codeberg.org/shufflecake/shufflecake-c/issues, please report new bugs by submitting new issues there. Alternatively, you can send an email to bugs@shufflecake.net. For reporting security issues and any vulnerability that might impact the security of users, please refer to the instructions in SECURITY.md.

Outstanding known bugs and/or limitations:

  • Only a maximum of 15 volumes per device is supported.
  • There is (currently) no protection against multi-snapshot attacks.

Maintainers

Elia Anzuoni <elianzuoniATgmail.com>

Tommaso "tomgag" Gagliardoni <tommasoATgagliardoni.net>

Copyright The Shufflecake Project Authors (2022)

Copyright The Shufflecake Project Contributors (2022)

Copyright Contributors to the The Shufflecake Project.

See the AUTHORS file at the top-level directory of this distribution and at https://www.shufflecake.net/permalinks/shufflecake-c/AUTHORS.

The program shufflecake-c is part of the Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) layer for Linux. See https://www.shufflecake.net.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Description
No description provided
Readme GPL-2.0 3.4 MiB
Languages
C 79.4%
Shell 18.9%
Makefile 1.7%