Saturday, August 08, 2015

Full Disk Encryption with Cyanogenmod CM12.1 on a Samsung Galaxy S4 Mini

Update August 9th: Just skip to the last line of this post where we realize that we could have spared us all of the hassles and resize2fs from within the running android system ☺.


If you try to enable full disk encryption on Cyanogenmod CM12.1 using the normal settings menu (Security -> Encrypt Phone) it doesn't work, the phone will just soft-reboot and nothing will have happened.

If you "logcat" the debugging log of your phone (using adb logcat) within the huge amount of data, some hint about what might have gone wrong can be found:

➜  ~  grep Cryptfs logcat_encryption.txt 
I/Cryptfs (  199): Check if PFE is activated on Boot
E/Cryptfs (  199): Bad magic for real block device /dev/block/platform/msm_sdcc.1/by-name/userdata
E/Cryptfs (  199): Error getting crypt footer and key
E/Cryptfs (  199): Bad magic for real block device /dev/block/platform/msm_sdcc.1/by-name/userdata
E/Cryptfs (  199): Orig filesystem overlaps crypto footer region.  Cannot encrypt in place.
E/Cryptfs (  199): Bad magic for real block device /dev/block/platform/msm_sdcc.1/by-name/userdata
E/Cryptfs (  199): Orig filesystem overlaps crypto footer region.  Cannot encrypt in place.

On android, the footer that tells the operating system that an partition is encrypted resides on the end of the filesystem and it needs a little space between the logical end of the filesystem in a partition, and the physical end of the partition to be squeezed in when converting a phone from unencrypted to encrypted.

http://forum.xda-developers.com/nexus-4/help/looking-encryption-footer-t2676700

Running the recovery system (boot while keeping Volume-Up and Home pressed), we can have a look at the partition sizes and filesystem details. We learn that on my S4 mini, the userdata partition (mmcblk0p24) has a size of 5685231 1k blocks, and the /data filesystem claims a size of 1421307 4k blocks.

$ adb shell
~ # cat /proc/partitions
major minor  #blocks  name
(...)
 179       24    5685231 mmcblk0p24
~ # tune2fs -l /dev/block/mmcblk0p24 
(...)
Block count:              1421307
(...)
Block size:               4096

As 5685231-1421307*4 = 3, that's only 3 meager 1k blocks at the end of the filesystem, whereas the encryption footer needs a space of at least 16k, the allmighty internet tells me. So, let's build a filesystem that leaves 128kByte of free space on the end as I don't know if Android 5 has enlarged the footer from what the websites I had found claims, or if there's some alignment requirement for it. So I'll be generous. (5685231-128)/4=1421275.75 so I'll create a ext4 filesystem occupying 1421275 4k blocks:

~ # mke2fs -b4096 -T ext4 /dev/block/platform/msm_sdcc.1/by-name/userdata 142127
(note: I made a mistake, ch0pped off the 5!)
mke2fs 1.41.14 (22-Dec-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
35600 inodes, 142127 blocks
7106 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=146800640
5 block groups
32768 blocks per group, 32768 fragments per group
7120 inodes per group
Superblock backups stored on blocks: 
32768, 98304

Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 33 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

Do I really have to mention at this point that this will erase all your files? Alternatively one could try "resizefs" to resize the filesystem, but that program isn't included in my recovery. Anyhow, it seems to be prudent to try encryption on an otherwise virgin install, as one risks data loss anyhow when performing the encryption process and there are reports of phones not booting up correctly after encyption had been enabled.

Then reboot the phone, do a half-hearted initial setup of the device, configure a simple PIN for testing, and encrypt your phone. (I also enabled debugging so that I can run logcat again to catch errors).

$ grep Cryptfs logcat_encryption_newfs.txt
(...)
I/Cryptfs (  196): Check if PFE is activated on Boot
E/Cryptfs (  196): Bad magic for real block device /dev/block/platform/msm_sdcc.1/by-name/userdata
E/Cryptfs (  196): Error getting crypt footer and key
E/Cryptfs (  196): not running with encryption, aborting
E/Cryptfs (  196): Bad magic for real block device /dev/block/platform/msm_sdcc.1/by-name/userdata
D/Cryptfs (  196): Just asked init to shut down class main
D/Cryptfs (  196): unmounting /mnt/shell/emulated succeeded
D/Cryptfs (  196): unmounting /data succeeded
I/Cryptfs (  196): keymaster version is 2
I/Cryptfs (  196): Using scrypt for cryptfs KDF
D/Cryptfs (  196): Just triggered post_fs_data
D/Cryptfs (  196): post_fs_data done
D/Cryptfs (  196): Just triggered restart_min_framework
I/Cryptfs (  196): Using scrypt for cryptfs KDF
I/Cryptfs (  196): Enabling support for allow_discards in dmcrypt.
I/Cryptfs (  196): load_crypto_mapping_table: target_type = crypt
I/Cryptfs (  196): load_crypto_mapping_table: real_blk_name = /dev/block/platform/msm_sdcc.1/by-name/userdata, extra_params = 1 allow_discards
I/Cryptfs (  196): Encrypting ext4 filesystem in place...
I/Cryptfs (  196): Encrypting group 0
I/Cryptfs (  196): Encrypting from sector 0
I/Cryptfs (  196): Encrypting group 1
I/Cryptfs (  196): Encrypted to sector 1356288
I/Cryptfs (  196): Encrypting from sector 16777216
I/Cryptfs (  196): Encrypted to sector 16867328
I/Cryptfs (  196): Encrypting from sector 16874496
I/Cryptfs (  196): Encrypted to sector 17014784

The phone will now reboot and ask for the PIN you entered. Unfortunately this takes *ages*! But if everything is fine, you can now setup your phone to your heart's content and set up a real password to have a securely encrypted phone. We'll have to see how stable this encrypted phone will be in daily use.

From Chris’ Miscellanea

Update: I made a mistake and chopped off the "5" at the end, so my filesystem only occupies 1/10 of the available space and has a completely unusable size of 500 MB :-(. So, to not have to start all over again, I'll try to resize the file system in place.

Login to your android device, and check the filesystem size. Indeed /data is completely ridiculous at 500MB.

➜  e2fs  adb shell
shell@serranoltexx:/ $ su
root@serranoltexx:/ # df
Filesystem               Size     Used     Free   Blksize
(...)
/data                  553.0M   490.2M    62.8M   4096

Check the sizes of the underlaying block device, and the dmcrypt mapper:

root@serranoltexx:/ # cat /proc/partitions
major minor  #blocks  name
(...)
 179       24    5685231 mmcblk0p24
(...)
 254        0    5685215 dm-0

Indeed, the crypted partition is exactly 16kB smaller (the crypt footer) than the raw block device. So we can hopefully let resize2fs autodiscover the target size. Unfortunately, we cannot access the block device hosting /data, and we can't umount /data because the android framework is still running. So we use the same method as the volume daemon to shutdown most of android. (your device will not no longer react to user input on the buttons or touch secreen):

root@serranoltexx:/ # setprop vold.decrypt trigger_shutdown_framework
root@serranoltexx:/ # umount /data
root@serranoltexx:/ # e2fsck -f /dev/block/dm-0       
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
(...)
(fix problems as they appear here)
root@serranoltexx:/ # resize2fs /dev/block/dm-0
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/block/dm-0 to 1421303 (4k) blocks.
The filesystem on /dev/block/dm-0 is now 1421303 blocks long.

I rebooted the phone the hard way via sync; echo b >/proc/sysrq-trigger.

Now /data is at the expected size of 5.5 GB.

➜  ~  adb shell df
Filesystem               Size     Used     Free   Blksize
(...)
/data                    5.4G   734.3M     4.7G   4096

Of course, now that we have found out how to resize an ext4 filesystem in place from within android, we realize that we could have made it that way from the beginning 😉. Without data loss. Just run the last 4 commands but using the physical emmc device and append the right number of blocks we need to resize2fs while the device is still unencrypted...

e2fsck /dev/block/mmcblk0p24
resize2fs /dev/block/mmcblk0p24 14221303

That should do the trick. Reboot and run the normal encryption process.

9 comments:

Scott said...

Thanks for sharing Chris. I am looking into doing similar with my Moto X (2013), but am curious how you determined the partition block that the encryption footer is in? Or is it simply that the major identifier of 179 is the data partition, with the last block being the footer that needs to be large enough for the encryption. I have multiple 179's as well as 259's.

I understand things are going to be different with my device, but thought I'd see if you might have some info.

Thanks for the help.

Scott

Unknown said...

Scott, you can get the device a particular filesystem is mounted at by looking at the output of the "mount" command...

➜ ~ adb shell mount|grep /data
/dev/block/dm-0 /data ext4 rw,seclabel,nosuid,nodev,noatime,journal_checksum,journal_async_commit,noauto_da_alloc,errors=panic,data=ordered 0 0

Here you see that my (currently encrypted) data partition is at /dev/block/dm-0, on your unencrypted phone this will be something like /dev/block/mmcblk0p123

If you have already encrypted your phone but want to know what the actual physical partiton backing up the encrypted storage is, you can look in sysfs;

root@serranoltexx:/ # cd /sys/class/block/dm-0/slaves
root@serranoltexx:/sys/class/block/dm-0/slaves # ls -l
lrwxrwxrwx root root 2015-08-11 20:09 mmcblk0p24 -> ../../../../platform/msm_sdcc.1/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p24

On this Galaxy S4 Mini, there's actually a subdirectory with symbolic links mapping "partition table names" (the "Samsung PIT") to physical devices.

root@serranoltexx:/dev/block/platform/msm_sdcc.1/by-name # ls -l
lrwxrwxrwx root root 2014-08-11 16:12 aboot -> /dev/block/mmcblk0p5
lrwxrwxrwx root root 2014-08-11 16:12 backup -> /dev/block/mmcblk0p16

Unknown said...

First thanks a lot for sharing all your tips!
I own a Samsung S4 mini and would like to give encryption a try.
In this thread I read that there are major performance issues when using encryption with the CM12.1 nightly builds:
http://forum.cyanogenmod.org/topic/105645-cm12-serranoltexx-bugs/page__st__40
Are you still able to use your phone normally after encrypting it?

Unknown said...

Another question: what recovery do you use/recommend to use?

Unknown said...

Stéphane, the performance implications are pretty bad, switching between applications can take many seconds. I'm actually quite surprised by this because there are hundreds of megabytes of memory free, and hence no need to free code and read it back again... But currently I consider the phone to be too slow for the typical user with encryption turned on.

I'm using the default cwm recovery, not an enhanced one.

Unknown said...

Thanks for the information.
I checked the RAM cache usage on my (unencrypted) CM12.1 nightly:
shell@serranoltexx:/ $ cat /proc/meminfo | grep Cache
Cached: 448624 kB
SwapCached: 0 kB
According to the "Applications" menu 665 MB of RAM are currently used by the system and my applications. So it seems that all most of my free ram is used as I/O cache.
What figures do you have on your encrypted phone?
With security breaches like stagefright it is probably easy to read the I/O cache.
I can imagine that FDE I/O blocks are either not cacheable or cached before decryption for security reasons.

Unknown said...

Here are some thoughts on applying CM12.1 nightly updates on an encrypted device.
I unpacked the latest nightly and found that the (signed) update script (called "updater-script") mounts /data (if not yet mounted) before running a check called otasigcheck.sh.
Any recovery lacking the ability to mount encrypted partition should fail a this point. The CWM recovery does not support encryption. The latest TWRP recovery I could find is more than one year old (2.7.1.0); my guess is that it cannot possibly support the latest FDE changes introduced AOSP Lollipop since Lollipop is less than one year old.
I guess that the otasigcheck.sh check could be removed, requiring a manipulation of every update package before install (patch the update script and possibly sign the changes).
Did you find a way to apply CM12.1 nightly updates on your encrypted device?

Unknown said...

Stéphane, on my encrypted phone, the "Control Panel" Apps screen shows 334MB/402MB/599MB system/apps/free. Commandline "free" outputs:

Mem: total 1.37GB, used 1,10GB, free 264MB, shared 0, buffers 26MB
Buffers: 1,08GB used, 291MB free

I don't think that there's anything special on an encrypted phone. As far as I know, using dm-crypt -or not- doesn't really make any difference to the rest of the kernel.

I haven't yet tried to apply any update, so I'm curious how this will work out.

Techmeister said...

Great post, I haven't managed to get encryption working since CM 11.

# grep Cryptfs motlog.txt
04-16 03:48:34.692 178 189 E Cryptfs : Bad magic for real block device /dev/block/platform/msm_sdcc.1/by-name/userdata
04-16 03:48:34.693 178 189 E Cryptfs : Not a valid ext4 superblock
04-16 03:48:34.694 178 189 E Cryptfs : Orig filesystem overlaps crypto footer region. Cannot encrypt in place.


I would love to test it out on my MotoG xt1032 but in recovery mode when I try to get its size so I can add 128 Kb at the end I get:

adb -s TA9330FTTL shell blockdev --getsz /dev/block/mmcblk0p36
27090688

adb -s TA9330FTTL shell tune2fs -l /dev/block/mmcblk0p36
tune2fs 1.42.9 (28-Dec-2013)
tune2fs: Bad magic number in super-block while trying to open /dev/block/mmcblk0p36
Couldn't find valid filesystem superblock.