讓TWRP支持解密高通data分區

現在新出品的手機,基本都加密了data分區,旨在保障用戶數據的安全。其中高通方案的手機使用的加密方案是QSEE(高通安全執行環境,Qualcomm Security Executing Environment),每次啓動設備時會有一個專門的過程來解密data分區。然而,TWRP Recovery默認並沒有附帶高通的加密組件,因此在啓動時會無法解密和訪問data分區,使得體驗大打折扣。因此必須把高通的加密組件從Android系統中移植過來。

QSEE加密組件的組成

高通QSEE組件由本體qseecomd程序、Keystore及其依賴庫組成。

首先是qseecomd加解密過程全由qseecomd完成,因此移植過程相對比較簡單。

Keystore是加解密過程所必需的“鑰匙”,爲一個so格式的庫文件,每個高通方案設備有屬於自己的Keystore,路徑爲/system/vendor/lib64/hw/keystore.<高通方案型號>.so(32位處理器型號請將lib64改爲lib)。

qseecomd運行還需依賴其它庫文件,查看依賴可使用readelf -d qseecomd

Dynamic section at offset 0x2cb8 contains 35 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x0000000000000001 (NEEDED)             Shared library: [libcutils.so]
 0x0000000000000001 (NEEDED)             Shared library: [libutils.so]
 0x0000000000000001 (NEEDED)             Shared library: [liblog.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libQSEEComAPI.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdrmfs.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc++.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 ......

值得注意的是,上述命令給出的依賴庫,除了libQSEEComAPI.solibdrmfs.so由高通提供外,其他的均爲安卓公用的運行庫,TWRP會提供它們。

另外,qseecomd的運行還離不開解釋器linker,使用readelf -l qseecomd,在輸出中可以看到qseecomd所使用linker的絕對路徑。

Elf file type is DYN (Shared object file)
Entry point 0x125c
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000001f8 0x00000000000001f8  R E    0x8
  INTERP         0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x0000000000000015 0x0000000000000015  R      0x1
      [Requesting program interpreter: /sbin/linker64]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000001dd8 0x0000000000001dd8  R E    0x10000
  LOAD           0x0000000000002c88 0x0000000000012c88 0x0000000000012c88
                 0x0000000000000540 0x0000000000000540  RW     0x10000
  DYNAMIC        0x0000000000002cb8 0x0000000000012cb8 0x0000000000012cb8
                 0x0000000000000270 0x0000000000000270  RW     0x8
  NOTE           0x0000000000000250 0x0000000000000250 0x0000000000000250
                 0x0000000000000038 0x0000000000000038  R      0x4
  GNU_EH_FRAME   0x0000000000001cc0 0x0000000000001cc0 0x0000000000001cc0
                 0x0000000000000024 0x0000000000000024  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000002c88 0x0000000000012c88 0x0000000000012c88
                 0x0000000000000378 0x0000000000000378  R      0x1

找到加密所需的文件

在上一步中,我們已經知道了加密需要用到哪些文件,那麼它們位於安卓系統的哪一個路徑?根據下面的表格,整理出它們所在的路徑,以及放置到TWRP根文件系統中的路徑。

文件 在Android系統中的路徑 TWRP中的路徑
qseecomd /system/bin/qseecomd /sbin/qseecomd
libQSEEComAPI.so /system/vendor/lib64/libQSEEComAPI.so[1] /vendor/lib64/libQSEEComAPI.so
libdrmfs.so /system/vendor/lib64/libdrmfs.so /vendor/lib64/libdrmfs.so

將文件複製到TWRP源碼中

Android設備配置文件(/device/<廠商名>/<設備名>)中,如果存在目錄recovery/root,那麼該目錄中的內容就會在編譯TWRP時,自動複製到TWRP的根文件系統中。因此,請將上一步中的文件,根據上表的路徑複製到其中。

使用patchelf修改qseecomd的linker路徑

系統環境與TWRP的環境還是有所差別的。爲了保證qseecomd能夠正確地找到解釋器linker,我們還需要使用patchelf工具,對qseecomd進行一番修改,否則運行時會提示“qseecomd: not found”,儘管qseecomd確實在指定的目錄中。

qseecomd默認的linker是/system/bin/linker64,而TWRP的linker則是/sbin/linker64。因此,我們需要這樣修改linker路徑:

patchelf --set-interpreter /sbin/linker64 qseecomd

修改完成後,再使用readelf -l qseecomd進行檢查,就可以發現修改成功了。

qseecomd註冊爲服務

qseecomd以服務的形式運行,它會在運行之時自動對data分區進行解密。想讓qseecomd作爲服務運行,需要修改init.recovery.qcom.rc,這是Android的init配置文件之一。

創建該文件,在其中寫入如下內容:

on property:ro.crypto.state=encrypted
    stop qseecomd
    start qseecomd

#
# qseecomd 的服務項
# 設置爲隨TWRP啓動而自動啓動
#
service qseecomd /sbin/qseecomd
    user root
    group root
    seclabel u:r:recovery:s0

# 
# 修復TWRP的一個Bug:刪除無效的bootdevice鏈接並重新創建
# 默認地,TWRP會在/dev/block目錄下創建一個bootdevice鏈接,指向啓動設備,
# 但因爲未知的原因使得該鏈接無效。因此需要重新創建之,否則qseecomd會無法識別啓動設備,導致出錯
#
on boot
    exec u:r:recovery:s0 -- /sbin/busybox rm -r /dev/block/bootdevice
    symlink /dev/block/platform/7824900.sdhci /dev/block/bootdevice


on fs
    #
    # 保險起見,在這個地方也嘗試重新創建設備鏈接
    #
    symlink /dev/block/platform/7824900.sdhci /dev/block/bootdevice

    # 
    # 設置qseecomd所需設備的權限
    #
    chmod 0660 /dev/qseecom
    chown system drmrpc /dev/qseecom
    chmod 0664 /dev/ion
    chown system system /dev/ion

設置TWRP參數

TWRP本身有解密模塊,並提供與qseecomd對接的接口,但默認沒有啓用。因此我們需要在BoardConfig.mk設置相應的選項:

TARGET_PROVIDES_KEYMASTER := true
TARGET_KEYMASTER_WAIT_FOR_QSEE := true

TARGET_PROVIDES_KEYMASTER指定設備是否具有用於解密的keymaster,keymaster正是解密必不可少的“鑰匙”,高通方案的設備會提供。而TARGET_KEYMASTER_WAIT_FOR_QSEE則指定是否等待qseecomd解密完成。其中,TARGET_KEYMASTER_WAIT_FOR_QSEE至關重要,它是qseecomd解密支持的重要開關,若不設置它,就和不帶加密組件無異。

調試

檢查工作狀態

判斷TWRP是否正常解密的依據,就是觀察啓動後會出現什麼畫面。如果啓動非常快,且顯示的是輸入密碼的窗口,而事實上手機並沒有使用密碼加密,而是保持默認加密狀態,那麼說明解密不成功,還需努力調試。如果啓動時間延長(定格在splash畫面),進入主界面後點擊底部的“日誌”按鈕顯示“Data successfully decrypted”,那麼則說明解密成功。

獲取日誌

並不是所有的設備都能遵照上述步驟成功爲TWRP啓用加密支持,各種各樣的問題都有可能出現。顯然,我們可以根據日誌,來檢查qseecomd的工作狀態——qseecomd會同時往內核日誌和logcat中寫入日誌。使用dmesgcat /proc/kmsg來獲取內核日誌;而在BoardConfig.mk中啓用logcat支持後,我們亦可以通過運行logcat來獲取qseecomd輸出的另一部分日誌。

啓用logcat支持的開關爲:

# Logcat
TWRP_INCLUDE_LOGCAT := true
TARGET_USES_LOGD := true

除此之外,我們還可以從TWRP這一邊展開分析。TWRP的解密過程也被記錄在TWRP本身的日誌中,閱讀/cache/recovery/last_log*即可瞭解。

總結體會

爲TWRP加入解密組件,看似比較難,實則並不難,關鍵在於不斷嘗試。筆者能獲得上面的成果,有賴於在反覆失敗後仍然能夠反覆嘗試,最終取得成功。在整個過程當中,日誌調試的作用舉足輕重,它反饋了TWRP與qseecomd組件運行時的一系列狀況,是分析故障的利器。


  1. 系統中,根目錄有一個/vendor,鏈接到/system/vendor

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章