[Huawei Mate 9 Guides, News, & Discussion] zxy_xda:
It's surprising that a bunch of people are interested in this article. But I have to say that some processes I mentioned in this article just happened to work. I don't necessarily understand why they work, which also means they probably cannot be generalized to any devices. Google is making security patches to every Android releases, which break some procedures in this article, including the vdc command. For anyone who wants to recover data from an encrypted device, I'm afraid you might have to do your own research such as reading the AOSP source code, because I havn't been following the changes in AOSP since this article was written, and sorry I cannot provide useful information. Finally I hope this article is helpful in some way and good luck.

-----------------------------------------------------------------------------------------------------------

About a year ago I encountered such a problem: https://xdaforums.com/mate-9/help/mate-9-how-to-decrypt-fbe-encrypted-t3735545

To summarize, I flashed a newer ROM with the file encryption enabled, while I already had my phone decrypted (userdata was not encrypted). I forced rebooted my phone when it was booting and encrypting my files. As a consequence, I couldn't unlock my phone or access the encrypted files.

This guide is about how to retrieve these encrypted files.

Requirements:

Device: Huawei Mate 9 MHA-AL00

ROM: EMUI 5.0.1 B233

(This guide might also work on other Huawei devices or other EMUI 5.)

Please make sure that your device is "decrypted" (i.e. boot without "fileencryptioninline" option), rooted, has busybox installed and avaliable for using.

A complete userdata partition image that you need to decrypt. Usually you can make this image in TWRP using dd command.

(In this guide, you are supposed to dump the encrypted userdata partition and flash another usable system)

A terminal APP (like juicessh) to execute commands. Alternatively, you can use adb shell.

Backup your current data, just in case.

A linux system (I'm using ubuntu 1804 as example).

(hopefully) you are familiar with some linux commands.

Notes:

If you encounter such situation (I described at the beginning), you can probably try to fix the system first (for example, make a backup and delete /data/system/gatekeeper.password.key and /data/system/gatekeeper.pattern.key to disable lock screen password).

Encryption option:

There is a mount option called "fileencryptioninline" in fstab.hi3660 in rootfs of origin kernel, which could be recognized by init so that it can control whether to perform a file based encryption (FBE). Removing this option (or changing to "encryptable"?) can disable FBE (before userdata partition is encrypted).

How does FBE encrypt files:

Google has developed fscrypt in linux kernel to implement FBE. To use fscrypt, a key with description "fscrypt:xxxxx" should be added to kernel, where "xxxxx" is a 8 byte value in HEX format. This value is unique and used to identify encryption policy. f2fs can retrieve this key. If we want to encrypt some files, we use ioctl to set an encryption policy (which is the 8 byte value) to an empty directory. The files copied to it will be encrypted by the cooresponding key. If we access an encrypted file, f2fs will get its encryption policy and find the key that matches this policy. This key will be used to decrypt the file. Multiple keys and policies are allowed.

In order to protect the fscrypt keys (I described above), FBE uses keymaster to encrypt and store them to userdata partition. A set of encrypted keys usually consists these files: "encrypted_key" "keymaster_key_blob" "secdiscardable" "stretching" "version". Keymaster is able to use them and communicate with a hardware based Trusty TEE to obtain the real key for fscrypt. The decryption is related to hardware so only the device which creates these keys are able to decrypt them.

FBE has at least 3 sets of keys. (assumed that you are user 0):

global device key (global DE): stores in /data/unencrypted/key.

Policy: all directories in /data other than "lost+found", "system_ce", "system_de", "misc_ce", "misc_de", "media", "data", "user", "user_de".

device key (DE): stores in /data/misc/vold/user_keys/de/0.

Policy: usually the directories ended with "_de".

candidate key (CE): stores in /data/misc/vold/user_keys/cd/0/current.

Policy: usually the directories ended with "_ce" and /data/data, /data/media/0.

Please note that CE and DE keys should have already been encrypted by Global DE key

vold (looks like volume daemon)

vold is the volume manager of android (and it runs as a daemon). It can be controlled by vdc (volume daemon control?). In the source code of vold there is a command listener which defines the avaliable commands of vdc. vold controls the key management of FBE.

Steps:

Create a keyring called "e4crypt".

Unfortunately, android does not have a tool to manipulate linux key-management facility. To add this keyring, I'm using "add_key" system call.

A sample program and sample operations:

#include <stdio.h>
#include <unistd.h>
#include <linux/keyctl.h>
#include <sys/syscall.h>

int main() {
int ret = syscall(__NR_add_key, "keyring", "e4crypt", NULL, 0, KEY_SPEC_USER_SESSION_KEYRING);
if (ret != -1) {
printf("Successfully created keyring \"e4crypt\"\n");
}
else {
perror("add_key");
}
return 0;
}

Compile this code and run it on your phone. You can use android NDK to compile it. (Actually I think any arm/arm64 toolchain for linux will work). I don't want to download a very large NDK so I'm using gcc-aarch64-linux-gnu.

On ubuntu 1804:

(Use "sudo apt install gcc-aarch64-linux-gnu" to install this toolchain)

zxy@zxy-virtual-machine:~/add_keyring$ cat add_keyring.c
#include <stdio.h>
#include <linux/keyctl.h>
#include <sys/syscall.h>

int main() {
int ret = syscall(__NR_add_key, "keyring", "e4crypt", NULL, 0, KEY_SPEC_USER_SESSION_KEYRING);
if (ret != -1) {
printf("Successfully created keyring \"e4crypt\"\n");
}
else {
perror("add_key");
}
return 0;
}
zxy@zxy-virtual-machine:~/add_keyring$ aarch64-linux-gnu-gcc -static add_keyring.c -o add_keyring
zxy@zxy-virtual-machine:~/add_keyring$ ls
add_keyring add_keyring.c

On your phone (adb shell):

Assume that we've already placed the "add_keyring" executable binary in /data/add_keyring

HWMHA:/ $ su
HWMHA:/ # cd /data
HWMHA:/data # ls -l add_keyring
-rw-r--r-- 1 root root 546888 2018-12-29 23:31 add_keyring
HWMHA:/data # chmod +x add_keyring
HWMHA:/ # cat /proc/keys
032c30ec I--Q--- 1 perm 1f3f0000 0 65534 keyring _uid_ses.0: 1
0d64f2db I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
HWMHA:/data # ./add_keyring
Successfully created keyring "e4crypt"
HWMHA:/data # cat /proc/keys
032c30ec I--Q--- 1 perm 1f3f0000 0 65534 keyring _uid_ses.0: 2
0d64f2db I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
1db74fa6 I--Q--- 1 perm 3f010000 0 0 keyring e4crypt: empty
HWMHA:/data #

This step is completed if you see a keyring called "e4crypt".

Mount the partition image to your device.

You can copy the image file to a USB storage device and use otg so that you can access the partition image on your phone (but it seems to be unstable). In this guide I'll mount a samba share which contains that image on my phone.

My operation logs:

On ubuntu:

I've created a samba share called "image" which points to the directory containing that partition. The partition image file is called "sdd46". The IP address of this computer is 192.168.1.120

On your phone:

Prepare the partition image (sdd46):

HWMHA:/ $
HWMHA:/ $ su
HWMHA:/ # mkdir /computer
mkdir: '/computer': Read-only file system
HWMHA:/ # busybox mount -o remount,rw /
HWMHA:/ # mkdir /computer
HWMHA:/ # busybox mount -t cifs -o nolock,username=nobody '\\192.168.1.120\image' /computer
HWMHA:/ # ls /computer
sdd46

Mount this image (the "force_no_inline_enc" option is required):

HWMHA:/ # mkdir /decrypt_data
HWMHA:/ # busybox mount -t f2fs -o ro,force_no_inline_enc /computer/sdd46 /decrypt_data

Check if your image is successfully mounted:

HWMHA:/ # ls /decrypt_data/
adb camera fusion_daemon_rpipe inv_ipld_wpipe mediadrm ramdump system update
anr cota fusion_daemon_wpipe ioloader misc resource-cache system_ce user
apkpush cust gps ivp misc_ce samba system_de user_de
app cust_ver.bin hcs keyie misc_de sec_storage_data t vsftpd
app-asec custom.bin hisi_logs libnfc-nxp.conf nfc security takess vsftpd.conf
app-ephemeral dalvik-cache hw_init light nvram share takess.sh
app-lib daniuc.dex hwzd_logs local offlinelogs skin themes
app-private data img log ota ss timetest
app_acc drm inotify lost+found pppd_via su.img tmp
backup encrypted_flag inputie lp product.bin suhide.img tombstones
bootchart fpie inv_ipld_rpipe media property supersu unencrypted
HWMHA:/ # cd /decrypt_data/
HWMHA:/decrypt_data # cd misc
misc/ misc_ce/ misc_de/
HWMHA:/decrypt_data # cd misc
HWMHA:/decrypt_data/misc # ls vold
yVsKT2+BrPIOKcQdVYyetC

You can see an encrypted directory in /decrypt_data/misc/vold, which stores the CE and DE keys. If you can't find this directory, it might not be encrypted and should located in /decrypt_data/unencrypted/data/misc/vold.

Install Global DE key:

You need to copy global DE key to /data/unencrypted and execute:

vdc --wait cryptfs enablefilecrypto

My operation logs:

Copy Global DE key to /data/unencrypted:

HWMHA:/ $ su
HWMHA:/ # cd /data
HWMHA:/data # mkdir unencrypted
HWMHA:/data # cd unencrypted
HWMHA:/data/unencrypted # ls
HWMHA:/data/unencrypted # cp -nr /decrypt_data/unencrypted/key ./
HWMHA:/data/unencrypted # ls
key
HWMHA:/data/unencrypted # ls key
encrypted_key keymaster_key_blob secdiscardable stretching version
encrypted_key.backup keymaster_key_blob.backup secdiscardable.backup stretching.backup version.backup

then, install this key:

HWMHA:/data/unencrypted # cat /proc/keys
032c30ec I--Q--- 1 perm 1f3f0000 0 65534 keyring _uid_ses.0: 2
0d64f2db I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
1db74fa6 I--Q--- 1 perm 3f010000 0 0 keyring e4crypt: empty
HWMHA:/data/unencrypted # vdc --wait cryptfs enablefilecrypto
200 3966 1
HWMHA:/data/unencrypted #
HWMHA:/data/unencrypted # cat /proc/keys
032c30ec I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid_ses.0: 2
0d64f2db I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
1db74fa6 I--Q--- 1 perm 3f010000 0 0 keyring e4crypt: 1
258344d4 I--Q--- 1 perm 3d010000 0 0 logon fscrypt:773e9f60adca3172: 72

You can see a new key "fscrypt:773e9f60adca3172" is added to kernel.

Check if you can access CE and DE keys and copy them to /data/misc/vold

My operation logs:

Check if you can access CE and DE keys:

HWMHA:/data/unencrypted # cd /decrypt_data/misc
HWMHA:/decrypt_data/misc # ls vold
user_keys

Copy CE and DE keys to the right location:

HWMHA:/decrypt_data/misc # cd /data/misc/vold
HWMHA:/data/misc/vold # ls
bench
HWMHA:/data/misc/vold # cp -nr /decrypt_data/misc/vold/user_keys .
HWMHA:/data/misc/vold # ls
bench user_keys
HWMHA:/data/misc/vold # cd user_keys
HWMHA:/data/misc/vold/user_keys # ls
ce de
HWMHA:/data/misc/vold/user_keys # cd de/0/
HWMHA:/data/misc/vold/user_keys/de/0 # cat version
1HWMHA:/data/misc/vold/user_keys/de/0 #
HWMHA:/data/misc/vold/user_keys/de/0 #

Install DE key

Just set ro.crypto.type to "file" and execute this command:

vdc --wait cryptfs init_user0

My operation logs:

Before installing DE key you will see some ecrypted files protected by it.

HWMHA:/decrypt_data/user_de/0 # ls
++gBT,VFvFeD,vgVoSVpUqeDNoC Wno64AdMq3Wde+F8LqWYvWiAFaFIiU810wX84B
+ExRFZKrTrX5PAZWjgzJKV26in24FxSt Ws+aoxf5sborLpV0EZLhvA
+Lyki0vu0dbWrX5PvAq3g932ONE WyHV8MQblZaCmdNpO6WPQSN1TgQoGxzw3mn4vB
+T95aXkKGnakajMwgSxcblTh0+8Vp3RI X0WDXQ5BsVDV6u45CJ9etzjba9JkWeQG
..............

Check the keys in kernel:

HWMHA:/decrypt_data # cat /proc/keys
032c30ec I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid_ses.0: 2
0d64f2db I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
1db74fa6 I--Q--- 1 perm 3f010000 0 0 keyring e4crypt: 1
258344d4 I--Q--- 1 perm 3d010000 0 0 logon fscrypt:773e9f60adca3172: 72

You'll need to set a property before installing the key.

HWMHA:/decrypt_data # getprop ro.crypto.type

HWMHA:/decrypt_data # setprop ro.crypto.type file
HWMHA:/decrypt_data # getprop ro.crypto.type
file
HWMHA:/decrypt_data # vdc --wait cryptfs init_user0
200 10711 Command succeeded
HWMHA:/decrypt_data # cat /proc/keys
032c30ec I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid_ses.0: 2
0d64f2db I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
1db74fa6 I--Q--- 1 perm 3f010000 0 0 keyring e4crypt: 2
258344d4 I--Q--- 1 perm 3d010000 0 0 logon fscrypt:773e9f60adca3172: 72
3c670371 I--Q--- 1 perm 3d010000 0 0 logon fscrypt:521acd13c187513c: 72
HWMHA:/decrypt_data #

Check whether you can access the files protected by DE key.

HWMHA:/decrypt_data #
HWMHA:/decrypt_data # cd user_de/0
HWMHA:/decrypt_data/user_de/0 # ls
abcmeasurecorp.com.measureit com.huawei.bluetooth
androdns.android.leetdreams.ch.androdns com.huawei.ca
android com.huawei.camera
androidhwext com.huawei.compass
..............

Install CE key.

Just execute this command:

vdc --wait cryptfs unlock_user_key 0 0 "" ""

The last two arguments are empty strings.

My operation logs:

Before installing CE key you'll find some encrypted files protected by it.

HWMHA:/decrypt_data # cd media/0
HWMHA:/decrypt_data/media/0 # ls
0M8msgkIuhwegkVYqu2zvC OK0B0zzWFSQ5pDHwSlAIvA aNrURou98klfwIaGnFAdPA rHzJIvFcgtIcIz,WOjZrRD w59yxPZvec,eu9HMMdDpuB
7VDq++zOwS5xaV35TuZbmB WSWzdKdAYAC2Vc1jOs6tqA jz,xyRZMpSLq2ghtL158yA rokqUTbYC7eMhGrghh0CSB
8rMqWow5AXxsZqHqbZyN9C XyLh+kAVQ5ZWXlWrc7wc5D pjgHBo3uPcxDi13euKN4PB tZkWYvxkrEufTMZ47f89cD

Install the key:

HWMHA:/decrypt_data/user_de/0 #
HWMHA:/decrypt_data/user_de/0 # vdc --wait cryptfs unlock_user_key 0 0 "" ""
200 11848 Command succeeded
HWMHA:/decrypt_data/user_de/0 #
HWMHA:/decrypt_data/user_de/0 #
HWMHA:/decrypt_data/user_de/0 # cat /proc/keys
032c30ec I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid_ses.0: 2
0d64f2db I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
1db74fa6 I--Q--- 1 perm 3f010000 0 0 keyring e4crypt: 3
258344d4 I--Q--- 1 perm 3d010000 0 0 logon fscrypt:773e9f60adca3172: 72
30baee27 I--Q--- 1 perm 3d010000 0 0 logon fscrypt:e1294ea7636feee7: 72
3c670371 I--Q--- 407 perm 3d010000 0 0 logon fscrypt:521acd13c187513c: 72

You can see a new key "fscrypt:521acd13c187513c" is added to kernel.

Check whether you can access the files protected by CE key.

HWMHA:/decrypt_data # cd media/0
HWMHA:/decrypt_data/media/0 # ls
Alarms Android DCIM Download Movies Music Notifications Pictures Podcasts Ringtones backups baidu huawei

Nou you should be able to access the encrypted files.

Clean up:

After you have backuped up the files you wish to retrieve, please delete the keys you copied to /data and reboot your phone. Don't change any security settings (like lock screen password) before rebooting.

Unmount partitions:

busybox umount /decrypt_data
busybox umount /computer

References and useful links:

Offical FBE doc:

https://source.android.com/security/encryption/file-based

Some FBE source code analysis:

https://blog.csdn.net/myfriend0/article/details/77094890 (Chinese)

https://github.com/novelinux/android/wiki/Android-FBE (Chinese)

http://hooltech.com/android-p-fbe.html (Chinese)

Hardware-backed Keystore:

https://source.android.com/security/keystore/index.html

Trusty TEE:

https://source.android.com/security/trusty/index.html

Something about Huawei's Trustzone:

https://github.com/OpenKirin/Documentation/blob/master/04-Trustzone.md

fscrypt:

https://www.kernel.org/doc/html/v4.15/filesystems/fscrypt.html

Make sure you always backup your data before performing any flashing/upgrading, especially when you are using a non-official ROM. I have spent a lot of time reading posts and analyzing source code. Luckily I succeeded. This was a lesson telling me the importance of backup.