0%

fde加密与解锁

fde加密与解锁

加锁状态

有以下 几种加锁状态:

  • 默认
  • PIN 码
  • 密码
  • 解锁图案
  • 指纹
  • 人脸解锁

其中指纹加锁的前提是必须有pin/密码/解锁图案的其中一种。所以可以只看pin/密码/pattern图案解锁即可

首次启动默认密码的情况

首次启动时,设备会创建一个随机生成的 128 位主密钥,然后会使用默认密码存储的盐对其进行哈希处理。默认密码是default_password。不过,设备还会通过 TEE(例如 TrustZone)为生成的哈希签名。TEE 会使用相应签名的哈希来加密主密钥。

密码加密

在已加密的设备上设置安全密码或更改安全密码

当用户在设备上设置 PIN 码/pattern图案密码或password时,只有 128 位的密钥会被重新加密并存储起来,加密设备的主密钥并不会改变。
当用户选择在设置中更改或移除密码时,界面会向 vold 发送 cryptfs changepw 命令,然后 vold 会使用新密码重新加密磁盘主密钥。

默认密码和用户设置的安全密码都是用来加密磁盘主密钥master_key的。

加密流程

设置了安全密码下解密手机流程

手机开机后,通过FallbackHome会 startActivity(homeIntent),
在开机过程中,会先跑到CryptKeeper.java(定义了intent-filter android.intent.category.HOME,且priority比较靠前)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                 <activity android:name=".CryptKeeper"
3378 androidprv:systemUserOnly="true"
3379 android:immersive="true"
3380 android:launchMode="singleTop"
3381 android:excludeFromRecents="true"
3382 android:theme="@style/Theme.MiuiCryptKeeper"
3383 android:configChanges="mnc|mcc|keyboard|keyboardHidden|uiMode|touchscreen"
3384 android:windowSoftInputMode="adjustResize"
3385 android:screenOrientation="portrait"
3386 android:process=":CryptKeeper">
3387 <!-- END -->
3388 <intent-filter android:priority="10">
3389 <action android:name="android.intent.action.MAIN" />
3390 <category android:name="android.intent.category.HOME" />
3391 <category android:name="android.intent.category.DEFAULT" />
3392 </intent-filter>
3393 </activity>

先调用setupUi方法

1
2
3
4
5
6
// 如果部分加密失败,跳转到恢复出厂设置
9 if (mEncryptionGoneBad || isDebugView(FORCE_VIEW_ERROR)) {
490 setContentView(R.layout.crypt_keeper_progress);
491 showFactoryReset(mCorrupt);
492 return;
493 }

通过StorageManagerService查询passwordType,最终传递到vold中通过cryptfs_get_password_type方法查询密钥类型是pattern/passwd/pin的哪个。这个方法是通过查询userdata块设备尾部存储的footer信息查出来的,而在加密的时候,也会根据用户密码的类似保存这样的type信息最终存储到设备的footer中

CryptKeeper根据用户密码类型显示对应的密码输入页面,即refreshUnlockEntry(passwordType)函数
对于密码类型,注册了监听类
passwordEntryInit

1
2
3
4
5
6
7
8
9
10
11
if (mPasswordEntry != null && !mCooldown){
872 // MIUI DEL:
873 // mPasswordEntry.setOnEditorActionListener(this);
874 mPasswordEntry.requestFocus();
875 // Become quiet when the user interacts with the Edit text screen.
876 mPasswordEntry.setOnKeyListener(this);
877 mPasswordEntry.setOnTouchListener(this);
878 mPasswordEntry.addTextChangedListener(this);
879 // MIUI ADD:
880 mMiuiKeyboardView.addKeyboardListener(mKeyboardActionListener);
881 }

mKeyboardActionListener的onKeyBoardOK时,即按了发送enter键后,会将输入的密码传出,发送给StorageManagerService
最终传给vold,decryptStorage(String password)-> cryptfs_check_passwd(passwd.c_str)

测试密码

vold通过test_mount_encrypted_fs对用户密码解密出磁盘主密钥,通过磁盘主密钥对设备进行挂载,如果能挂载上,则说明用户密码是正确的

1
2
decrypt_master_key(passwd, decrypted_master_key, crypt_ftr, &intermediate_key,
&intermediate_key_size)

小结

通过上述解密过程,用户密码是明文的形式,并没有再次对用户密码进行加密。这个过程应该是可以模拟的,如果可以在recovery模式下模拟出pattern/passwd/pattern三种模式的输入,是可以在recovery模式下解密用户设置了安全密码的fde的数据的