LUKS: Plausible deniability on crypto containers

Since several years, we have faced a “transparency campaign” on cryptography. That means that the cipher announces itself as an “encrypted container”. This suppose a serious risk by exposing you to a rubber-hose attack.

LUKS (Linux Unified Key Setup) which is used by common Linux distributions is not the exception. But there is a hope to provide some kind of privacy.

LUKS Self announcement:

As we mentioned above, LUKS announce himself by his own header. This is the default way linux cipher anything.

Any forensic procedure will indicate that we are using an encrypted device:


And confirmed using the “file” tool:

[root@ghost ~/tmpfs]# file cryptocontainer.img                                      
cryptocontainer.img: LUKS encrypted file, ver 1 [aes, xts-plain64, sha1] UUID: 7b11722e-7f02-4dd7-8d85-9bb1d349889d

the first 4096 bytes of the partition is the LUKS header.

Detaching the header: LUKS Concept for double factor cryptography.

Detaching the header provide us two mechanisms to protect ourselves from rubber hose attack, and one more for other kind of attack:

  1. We can deny that the cryptocontainer is in fact a crypto container. It could be a random data generated by /dev/random. This is feasible since a good hard drive crypto algorithm (like aes-xts or serpent-xts) outputs something with the same distribution and randomness of raw random data.
  2. You can separate the header and send the header to another location. Moreover, the header could be in possession of someone else in another country with strict instructions to not accept any demand (even if your life is threatened).
  3. Dividing the header from the encrypted body into a tiny device that could be detached after usage, and easily hided, could be useful if you don’t want  the header to be compromised and cracked offline.

We have many legitimate cases were this process could be used:

  • You have a laptop with special work belonging to your company. Your company does not want a competitor to take your laptop by some criminal and get the work for free.
  • A financial institution can now protect their assets from criminals trying to steal and sell inside information.

Detaching the header: Creating the Encrypted Container.

To create a crypto container, we must first proceed to create the header space, and then the data space.

The header space should be created directly on the drive that will be detached. By example I have an thumb-drive that will contain the header:

[root@ghost /run/media/user/7EA1-3440/cryptoc]# dd if=/dev/zero of=header.tmp bs=1M count=0 seek=2
0+0 records in
0+0 records out
0 bytes (0 B) copied, 0.0163393 s, 0.0 kB/s

now we can create our encrypted container (eg. 128M encrypted device), with random data inside (remember to change the directory).

[root@ghost /run/media/user/7EA1-3440/cryptoc]# cd
[root@ghost ~]# dd if=/dev/urandom of=container.img bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 10.8608 s, 12.4 MB/s

At this point, we are able to start the formatting process:

[root@ghost ~]# cryptsetup -v --header /run/media/user/7EA1-3440/cryptoc/header.tmp --iter-time=10000 --cipher=serpent-xts-plain64 --key-size=512 --hash=sha512 --use-random luksFormat container.img                                        
This will overwrite data on /run/media/user/7EA1-3440/cryptoc/header.tmp irrevocably.                                                                                                                                                        
Are you sure? (Type uppercase yes): YES                                                                                                                                                                                                      
Enter passphrase:                                                                                                                                                                                                                            
Verify passphrase:                                                                                                                                                                                                                           
Command successful.

Now container.img looks like random data 🙂


And header.tmp looks like LUKS header:


[root@ghost ~]# cryptsetup luksDump /run/media/user/7EA1-3440/cryptoc/header.tmp
LUKS header information for /run/media/user/7EA1-3440/cryptoc/header.tmp
Version: 1
Cipher name: serpent
Cipher mode: xts-plain64
Hash spec: sha512
Payload offset: 0
MK bits: 512
MK digest: 1c f0 b7 6c d5 e2 aa d0 0d 78 ac 78 95 e9 d1 75 3c c6 f9 5f 
MK salt: a5 e8 84 e1 76 8c 3e 5e 4d 9e f8 5c 3f 12 dd 12 
 14 83 dc 02 df b7 fb 23 28 b9 90 0b a2 aa 5d 4f 
MK iterations: 168750
UUID: b56a8959-2ada-486e-9ed9-dd8e71fd4493
Key Slot 0: ENABLED
 Iterations: 685224
 Salt: e2 45 08 c0 db cf af 89 a3 e8 9b 58 a1 51 3c ad 
 7f 81 de b6 0f 4c 87 bd 97 c1 5d c7 f2 aa 32 a8 
 Key material offset: 8
 AF stripes: 4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

Detaching the header: Formatting the Encrypted Container.

Now, we have to give a format to the encrypted container, we like btrfs, so let’s show you the thing…

 [root@ghost ~]# cryptsetup luksOpen --header /run/media/user/7EA1-3440/cryptoc/header.tmp container.img container                                                                                                                            
Enter passphrase for container.img:                                                                                                                                                                                                          
[root@ghost ~]# mkfs.btrfs /dev/mapper/container 
SMALL VOLUME: forcing mixed metadata/data groups                                                                                                                                                                                             
WARNING! - Btrfs v3.14.2 IS EXPERIMENTAL                                                                                                                                                                                                     
WARNING! - see before using                                                                                                                                                                                     
Turning ON incompat feature 'mixed-bg': mixed data and metadata block groups                                                                                                                                                                 
Turning ON incompat feature 'extref': increased hardlink limit per file to 65536                                                                                                                                                             
Created a data/metadata chunk of size 8388608                                                                                                                                                                                                
fs created label (null) on /dev/mapper/container                                                                                                                                                                                             
        nodesize 4096 leafsize 4096 sectorsize 4096 size 128.00MiB                                                                                                                                                                           
Btrfs v3.14.2                                                                                                                                                                                                                                
[root@ghost ~]# mkdir /mnt/container
[root@ghost ~]# mount /dev/mapper/container /mnt/container 
[root@ghost ~]# df -h | grep container
/dev/mapper/container 128M 32K 124M 1% /mnt/container

Now its ready 🙂

every time you need to mount it again, you just need to:

[root@ghost ~]# cryptsetup luksOpen --header /run/media/user/7EA1-3440/cryptoc/header.tmp container.img container                                                                                                                            
Enter passphrase for container.img:
[root@ghost ~]# mount /dev/mapper/container /mnt/container

Leave a Reply