THIS TUTORIAL IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL I
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS TUTORIAL, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
Motivation and idea
Starting with Android 3.x, the system theoretically supports encrypting the personal data on your device. But this has several caveats:
- it turns out that AOSP only supports encrypting /data, leaving other personal data (e.g. your pictures or storage from varios messengers) completely unencrypted on internal (emulated) or external SD storage.
- ever since, the partitioning of /data to a small, limited area leads to "no space left" issues (that's why many people go for app2sd etc.)
- in case your device suffers from physical damage, you usually loose all data you didn't backup previously.
- in case you want to sell or dispose your broken device you never know who will get access to your data anywhere in the future.
- securely wiping flash memory is complicated due to the fact that many controllers do not let you access their trim areas. Having built-in flash makes the situation even worse, especially because almost no manufacturer provides even a "manufacturer-declared-secure" wiping method - unlike some SSD drive vendors.
In this tutorial I will describe how I managed to move all personal data (probably excluding cached data, but this could be enhanced) to my external microSD card, overcoming these issues at the expense of a few drawbacks:
- (micro)SD cards are usually much slower than internal flash: boot time is about 2x slower and some apps feels a little slower, though not sluggish
- the mod requires root
- on most devices the mod also requires a modified boot image (due to change in initial RAM disk)
- it's pretty complicated to set it up (but following this guide can save you many efforts I already invested)
- mounting storage over MTP / USB is currently broken
Although this is more a proof-of-concept, I have been running this setup for a couple of days now as my daily driver without significant issues. I had some force-closes in Firefox, but I don't relate them to this mod and other browsers seem to work fine.
Enough said, let's get to work and move all personal data to your external SD card!
CURRENTLY, THIS GUIDE IS TARGETED AT ADVANCED USERS / DEVELOPERS / EXPERTS AND THUS ONLY COVERS THE ESSENTIAL BASICS, NOT THE DETAILS!
FOLLOWING THE PROCESS, YOU WILL LOOSE ALL YOUR PERSONAL DATA ON YOUR DEVICE! MAKE BACKUPS FIRST!!!
The tutorial is based on OmniROM 4.4 and TWRP. With not too much effort, it could be adopted to earlier Android Versions based on AOSP 4.0, probably even 3.0. (most likely, the location and internal layout of some configuration files will vary). Please note that I tried it only on one device, your milage may vary!
Step 1: Find out your partition layout
First off, you need to find out which devices are used for holding which data partitions. You can play around with "mount" or simply look in your fstab files which are located in /fstab.vendor in KK. While in some cases the devices are listed i.e. "by-name", the fstab files of custom recoveries often list the "real" device names. I.e. on my Xperia V they are as follows:
Internal Data partition: /dev/block/platform/msm_sdcc.1/by-name/Userdata Internal, emulated SD card: /dev/block/mmcblk0p15 First partition of external SD card: /dev/block/mmcblk1p1
After backing up everything, run the usual Android encryption process so your data partition (in this case: /dev/block/platform/msm_sdcc.1/by-name/Userdata) will be encrypted by means of standard 128bit AES Android encryption.
Step 3: Extract the cryptofooter
Boot into TWRP recovery (don't unlock your /data if prompted!) and connect via ADB as root. Usually, the crypto footer is stored in the last 16384 bytes of your partition (but check your fstab to be sure). Now determine the size of your partition with:
fdisk -l /dev/block/platform/msm_sdcc.1/by-name/Userdata
Disk Userdata: 2147 MB, 2147483648 bytes 255 heads, 63 sectors/track, 261 cylinders, total 4194304 sectors Units = sectors of 1 * 512 = 512 bytes ...
dd if=/dev/block/platform/msm_sdcc.1/by-name/Userdata of=/cryptofooter bs=1 seek=2147467264 count=16384
Step 4: Prepare the external SD card:
We de not want to partition the SDcard, thus we will not put any partition table on it. Nevertheless, we need to determine its exact size using fdisk:
fdisk -l /dev/block/mmcblk1p1 Disk mmcblk1: 31.9 GB, 31914983424 bytes 255 heads, 63 sectors/track, 3880 cylinders, total 62333952 sectors Units = sectors of 1 * 512 = 512 bytes ...
dd if=/cryptofooter of=/dev/block/mmcblk1= bs=1 skip=31914967040 count=16384
For later testing, we copy over the existing (encrypted) data partition to the SD card:
dd if=/dev/block/platform/msm_sdcc.1/by-name/Userdata of=/dev/block/mmcblk1p1
dd if=/dev/zero of=/dev/block/platform/msm_sdcc.1/by-name/Userdata
Step 5: Modifying fstab and init files:
Now we will need to modify the fstab files and init so they will reflect the new layout. On most devices, this requires compiling a new rootfs. This can be either done by uncompressing your boot.img, making the changes and recompressing it or recompiling it from sources. The modified boot.img has to be flashed back to the device, usually via fastboot.
In particular, we need to tell Android not to use the internal userdata partition at all, to mount the emulated sd card as usual and to use the external storage for /data using an encrypted ext4 filesystem. In my case, the modified fstab.qcom looks like this:
/dev/block/mmcblk1 /data ext4 noatime,nosuid,nodev,barrier=1,data=ordered,noauto_da_alloc wait,check,encryptable=footer,length=-16384 /devices/platform/msm_sdcc.1/mmc_host/mmc0 auto ext4 defaults voldmanaged=sdcard0:15,nonremovable,noemulatedsd #/devices/platform/msm_sdcc.3/mmc_host/mmc1 auto auto defaults voldmanaged=sdcard1:auto /devices/platform/msm_hsusb_host auto auto defaults voldmanaged=usbdisk:auto
We also need to modify init (in my case through sony.init.rc) to avoid getting the external sd card being treated as sdcard during boot by uncommenting the relevant lines:
chmod 0701 /mnt/media_rw mkdir /storage 0775 system system mkdir /mnt/media_rw/sdcard0 0700 media_rw media_rw # mkdir /mnt/media_rw/sdcard1 0700 media_rw media_rw mkdir /mnt/media_rw/usbdisk 0700 media_rw media_rw mkdir /storage/sdcard0 0775 system system # mkdir /storage/sdcard1 0775 system system mkdir /storage/usbdisk 0775 system system export EXTERNAL_STORAGE /storage/sdcard0 # export SECONDARY_STORAGE /storage/sdcard1 # for backwards compatibility symlink /storage/sdcard0 /sdcard symlink /storage/sdcard0 /mnt/sdcard # symlink /storage/sdcard1 /ext_card # symlink /storage/sdcard1 /mnt/ext_card symlink /storage/usbdisk /usbdisk symlink /storage/usbdisk /mnt/usbdisk
With all this set up, we can now boot again into our system. It should ask you for your encryption password (it's the same as you've set it in step 2) and you should notice that it runs a little slower - because SD cards are usually slower than internal flash. You will notice that the size of the internal space and external storage has not changed - we will fix this in the next step.
Step 7: Tweak the cryptofooter and reformat the SD card:
Now comes the fun part: Android determines the size of encrypted filesystems not by information from the filesystem, but by the size as it is stored in the cryptofooter. Therefore, we need to modify the information there. The cryptofooter is a complicated mess. Luckily, there is a great guide which describes its structure much better than the source code itself:
You will need to use a hex editor to edit the from bytes between Offset 0000:0018 and 0000:001B to match the size of your SD card. But please leave enough bytes at the end, at least for the cryptofooter!
Write back your modified cryptofooter as outlined in step 4 and boot into TWRP. Unlock your /data (which is now served from SD), connect via ADB and check the size of your encrypted device using fdisk:
fdisk -l /dev/block/dm-0
Step 8: Adjust internal SD.
Now, you are ready to reboot into your system serving its freshly wiped, encrypted data from your external SD! Be amazed by the space you now have for your internal Userdata! Unfortunately, it will still serve "internal SD" from internal flash. First, create a directory on the sdcard to hold it using a root shell:
# mkdir -p /data/sdcard0
# busybox mount -bind /data/sdcard0 /mnt/media_rw/sdcard0 # am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///storage/sdcard0
- Suggestions for correctly mounting the sdcard0 inside data at boot time without the bind-mounting is warmly welcome.
- Some (Stock) ROMs allow you to encrypt both SD "cards", but the implementations I have seen so far seem to be vendor-specific and closed source. Although I noticed that encrypting internal SD seems to work with AOSP out-of-the-box on some devices without external SD (e.g. Nexus S) I didn't find any Custom ROM for my Xperia V which worked with encrypted any of the SDs when putting the "encryptable=sdcard" flag in the fstab file: The storage seems to have been encrypted, but Android simply fails to mount it.
All data 2 encrypted, removable SD, Tool/Utility for the Android General
Last Updated 2015-01-08