4

I just read this discussion between Linus Torvalds and (among others) Milan Broz, one of dm-crypt's maintainers.

I am intrigued by the the following part of the discussion :

Linus Torvalds: I thought the people who used hidden ("deniable") things didn't actually ever use the outer filesystem at all, exactly so that they can just put the real encrypted thing in there and nor worry about it.

Milan Broz: Well, they actually should "use" outer from time to time so the data looks "recent" and for the whole "hidden OS" they should be even able to boot to outer decoy OS on request, just to show that something working is there.

In theory, I agree with Milan's statement, using the decoy data is a good thing to do to increase credibility. But how do you achieve that in practice? E.g., how can you write to the outer volume without risking to overwrite the inner volume?

I have been using hidden LUKS volumes for years now, combining detachable headers and data offset. Usually I start by creating a small LUKS-encrypted outer volume (let's say 20 GB), I format it with EXT4, I fill it with decoy data, then I increase this outer volume's size (to for example 500 GB), and I create the inner volume with an offset of 25GB for example.

And after that I do what Linus said, I religiously avoid to touch the outer volume's decoy data, out of fear of damaging the inner volume's data.

Is there a way to refresh the outer volume's data, without risking to damage the inner volume's data? E.g., is there a tool to write specifically on the 20 first Gigs of the outer volume, making sure to not mess with the 480 following gigs?

I am using both HDDs and SSDs, so the question applies to both.

2 Answers 2

1

There are probably a few ways to do this with reasonable safety, with potentially different approaches if starting with a new outer volume or an existing one.

Probably the best way to do this would be with the debugfs setb command on the unmounted outer filesystem device to mark range(s) of blocks that belong to the inner volume before mounting the outer filesystem and updating files there.:

debugfs -c -R "setb <inner_start_blk> <inner_count>" /dev/<outer>

setb block [count]
    Mark the block number block as allocated.  If the optional argument
    "count" is present, then "count" blocks starting at block number 
    "block" will be marked as allocated.

If there are disjoint ranges to the file, then multiple setb commands could be scripted writing by piping a file with block ranges like:

setb <range1> <count1>
setb <range2> <count2>
:

to debugfs reading the file debugfs -c -f <file> /dev/<outer>.

If you wanted to be a bit more clever than just packing the inner volume at the end of the outer filesystem, the inner volume could initially be created with fallocate -s 32M mydir/inner in the the outer filesystem, then the block range could be generated from debugfs:

# debugfs -c -R "stat mydir/inner" /dev/vg_root/lvhome
Inode: 263236   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 2399864846    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 32499577
File ACL: 0
Links: 1   Blockcount: 63480
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x63c98fc0:62bb0a38 -- Thu Jan 19 11:45:20 2023
 atime: 0x63cee835:5e019630 -- Mon Jan 23 13:04:05 2023
 mtime: 0x63c98fc0:559e2928 -- Thu Jan 19 11:45:20 2023
crtime: 0x63c98fc0:41974a6c -- Thu Jan 19 11:45:20 2023
Size of extra inode fields: 32
Extended attributes:
  security.selinux (37) = "unconfined_u:object_r:user_home_t:s0\000"
EXTENTS:
(0-7934):966656-974590

In this case, the ~32MB (7935x4KiB block) file is in blocks 966656-974590, so this would use setb 966656 7935 to mark those blocks used. The inode should be erased with clri <inum> to prevent the allocated block range from being visible afterward.

The blocks allocated in the outer filesystem by debugfs setb would remain allocated until the next time that e2fsck was run on the outer filesystem. That could potentially "expose" those blocks are in use if someone was really paying attention, so they could optionally be cleared again after the outer filesystem was unmounted, using `debugfs -c -R "clrb <inner_start> <inner_count>" /dev/", or kept allocated to avoid the inner filesystem from potentially being corrupted.

5
  • Thanks. Marking this as an accepted answer, though I didn't test yet. But yes, that seems to be a promising approach. A few thoughts and questions : Commented Mar 23, 2023 at 8:46
  • If you wanted to be a bit more clever than just packing the inner volume at the end of the outer filesystem : I don't thing there's the need to be "more clever", because I also encrypted my outer volume in the first place and filld empty space with random data (before creating the inner volume). So there's nothing suspicious to see scrambled data at the end of the outer volume. At least that's my understanding. Commented Mar 23, 2023 at 8:47
  • until the next time that e2fsck was run on the filesystem : I suppose you talk about the outer filesystem. Until now I carefully avoided to use e2fsck on the outer filesystem, because I was scared that it would recreate the superblock copies that were initially on the space now occupied by the inner filesystem. It's my understanding that when you create an EXT4 filesystem, it puts copies of the superblock all along the disk. So when I created my inner FS, some of those copies of the outer FS's superblock are potentially overwritten. Does e2fsck on the outer FS recreate those copies ? Commented Mar 23, 2023 at 8:47
  • An other idea I had was to shrink the outer volume back to 20 GB, refreshing the data, then increase again the outer volume to 500 GB, and hoping the inner volume hasn't been damaged in the process. But again, I fear that increasing the outer volume back to 500 GB will create new copies of the superblock along the outer FS, and thus overwriting data of the inner FS Commented Mar 23, 2023 at 8:47
  • Yes, e2fsck on the outer filesystem will definitely rewrite superblocks, and maybe group descriptors, bitmaps, and other in use metadata that overlaps with the inner filesystem. How much of this metadata in use at the end of the device depends on the formatting options. It is also possible (when first creating the outer filesystem at the full size) to specify options like "sparse_super2" to force all the metadata to be at the start of the volume. You can check which blocks are actually used with "dumpe2fs <outer>". Commented Mar 24, 2023 at 21:11
0

I don't use plausible deniability myself, so consider this a comment.

You could use the device mapper for the job (dmsetup).

It allows you to set up linear mappings (sector ranges that map to actual data), error mappings (sector ranges that don't exist and simply produce read/write errors), zero mappings (sector ranges that discard writes and return zeroes on reads), snapshots (copy-on-write overlays), ...

So you can fashion a block device where only the outer volume area is visible, the inner volume is protected, and writes to the inner volume will effectively be discarded or only temporarily stored in a snapshot area. And attempted reads in those areas could either yield zeroes or read errors.

You could mount or even spin up a VM on that outer volume and it would have no way to damage or access your inner volume at all. No such promises when using it without this layer of protection, though.

Another option is to allocate space by creating files in the outer volume and then use the dm-linear to create a usable block device out of that allocated filespace (filefrag will show you the sector ranges allocated for each file). That way the files of the outer filesystem would protect the inner volume.

This approach would allow you to use the outer filesystem freely, and even run TRIM/discard on it. Anything would be fine as long as the files representing the inner volume remain untouched. This also assumes the outer volume filesystem will not relocate/rewrite file contents on its own accord (no defrag, recompress, dedup, ...).

5
  • I'm not sure I understand everything here. I never used device mappers directly, only through LUKS or LVM. What would be the advantages/disadvantages of your approach compared to LustreOne's solution ? Commented Mar 25, 2023 at 7:40
  • It would be filesystem-agnostic. No filesystem specific tools required. You'd have to keep metadata of inner/outer sector ranges somewhere, but you already have that problem with the LUKS header. Otherwise just use --tcrypt-hidden instead (the only plausible deniability mode that cryptsetup officially supports as far as I'm aware?) but it does not protect the volumes from one another (no metadata). Of course that metadata could be kept in the hidden volume but it's not done. So you have to come up with your own solution. Or ditch plausible deniability altogether... ;-) Commented Mar 25, 2023 at 8:21
  • In a way, ext4 is not a very suitable filesystem for an outer volume since it stores data all over the place (superblock backups and other things). Other filesystems are more restrained and tend not to write somewhere in the middle when there's still enough free space left at lower offsets. But there's no guarantee for anything so that's still relying on implementation details. Commented Mar 25, 2023 at 8:23
  • Regarding corruption, this approach wouldn't avoid it, but it would be the outer volume suffering corruption. Anything the outer filesystem writes into an area that belongs to the inner one, would simply be lost. Corruption of the inner volume would only happen when mounted without the device mapper layer between it, no way to avoid that one without revealing that something strange is going on. If you want both, you'd have to do something with LVM thin volumes? And somehow make the inner volume use extents that the outer volume would use dead last? So they would collide in the middle. Commented Mar 25, 2023 at 8:30
  • Plausible deniability is one big headache. ;-) Sorry I don't have a solution. Anyway, good luck. Commented Mar 25, 2023 at 8:30

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.