實作 dm-verity

Android 4.4 以上版本支援驗證開機程序,可選擇是否啟用 device-mapper-verity (dm-verity) 核心功能 以及對區塊裝置的完整性檢查。dm-verity 有助於防止永久的 Rootkit 可能持有 Root 權限,進而入侵裝置這個 功能可協助 Android 使用者判斷裝置是否處於相同狀態 都像是上次使用的時間

具備 Root 權限可能有害的應用程式 (PHA) 可能會在下列位置隱藏: 偵測程式和其他偽裝程式進行偽裝。根層級軟體可以 這通常比偵測工具更高的權限 「謊言」以便偵測程式

dm-verity 功能可讓您查看區塊裝置,也就是基礎儲存空間 判斷其是否與預期相符 此外還會從 0 自動調整資源配置 您完全不必調整資源調度設定這項作業會使用加密編譯雜湊樹狀結構。針對每個街區 (通常是 4k) 這種 SHA256 雜湊。

雜湊值儲存在網頁的樹狀結構中,因此只有頂層 「根」雜湊必須受到信任,才能驗證樹狀結構的其餘部分。Google Cloud 可以 修改任何區塊就等同於破壞加密編譯雜湊。 請參閱下圖,瞭解此結構的結構。

dm-verity-hash-table

圖 1:dm-verity 雜湊表

啟動分區已隨附公開金鑰,因此必須驗證該組金鑰 由裝置製造商在外部使用這組金鑰的用途是驗證簽章 並確認裝置的系統分區已受到保護 不變。

作業

dm-verity 防護位於核心中。因此如果取得 Root 權限的軟體會入侵 就會保留該存取權。為了避免這種情況 風險,大多數製造商都會使用裝置所附的金鑰來驗證核心。 裝置出廠後即無法變更車鑰。

製造商會使用該金鑰在第一層驗證簽名 系統啟動載入程式,接著會在後續層級驗證簽章 應用程式系統啟動載入程式,最終成為核心。每個製造商希望 利用已驗證 Boot 應具有驗證核心完整性的方法。 假設核心已通過驗證,核心可以查看區塊裝置 並在掛接的情況下進行驗證。

驗證區塊裝置的方法之一是直接對內容進行雜湊處理,然後進行比較 轉換為儲存值不過,嘗試驗證整個區塊裝置 這會消耗裝置的大部分電力。裝置 因此應用程式在使用前會大量消耗

而是會分別驗證區塊,且只有在每個區塊 允許或拒絕要求讀取記憶體時,系統會平行雜湊處理區塊。雜湊為 完成樹狀結構的驗證後既然閱讀方塊是相當昂貴的 這項區塊層級驗證作業產生的延遲 也具有相對的名詞

如果驗證失敗,裝置會產生指出封鎖的 I/O 錯誤 無法讀取。看起來像是檔案系統損毀 。

應用程式可以選擇繼續執行,但不包含結果資料,例如 這些結果對於應用程式的主要功能不需要。不過 如果應用程式無法在沒有資料的情況下繼續,就會失敗。

轉發錯誤修正

Android 7.0 以上版本可藉由向前錯誤改善 dm.ver 穩定性 簡稱 FEC。實作 Android 開放原始碼計畫時,我們會以 Reed-Solomon 錯誤修正程式碼,並套用 稱為「交錯」可減少空間負擔 可以復原的毀損區塊數量。如要進一步瞭解 FEC,請參閱 「嚴格強制執行驗證開機程序,並更正錯誤」功能。

實作

摘要

  1. 產生 ext4 系統映像檔。
  2. 為圖片產生雜湊樹
  3. 為該雜湊樹狀結構建立 dm-verity 資料表
  4. 簽署該 dm-verity 資料表以產生資料表 簽章。
  5. 封裝資料表簽章和 dm-verity 資料表 深入文件中繼資料
  6. 將系統映像檔、詳細資訊中繼資料和雜湊樹狀結構串連起來。

請參閱 Chromium 專案 - 驗證開機程序 ,取得雜湊樹狀結構和 dm-verity 資料表的詳細說明。

產生雜湊樹狀結構

如前文所述,雜湊樹是 dm-verity 不可或缺的一環。 加密設定工具 產生雜湊樹狀結構或者,您也可以參閱以下連結,定義相容的廣告代碼:

<your block device name> <your block device name> <block size> <block size> <image size in blocks> <image size in blocks + 8> <root hash> <salt>

為了形成雜湊,系統會將系統映像檔分割為第 0 層,分割成 4K 區塊,每個區塊 指派了 SHA256 雜湊第 1 層僅結合這些 SHA256 雜湊而產生 分割成 4K 區塊,產生的圖片會比較小第 2 層結構完成 並使用第 1 層的 SHA256 雜湊。

這種做法會等到上一層的 SHA256 雜湊可以容納在單一圖層中 封鎖。取得該區塊的 SHA256 時,就會取得樹狀結構的根雜湊。

雜湊樹狀結構的大小 (以及對應的磁碟空間用量) 會隨著 驗證分區的大小實務上,雜湊樹狀結構的大小通常為 通常小於 30 MB

如果某一層中的區塊無法完全填滿 上一層的雜湊,您應該在這段程式碼中加上零,才能 預期應為 4 千次這樣一來,您就可以知道雜湊樹狀結構未移除,而且 並以空白資料完成

如要產生雜湊樹狀結構,請將第 2 層雜湊串連到圖層的雜湊中 1,第 3 層的雜湊是第 2 層的雜湊,以此類推。全部撰寫 輸出至磁碟請注意,這裡並未參照根雜湊的第 0 層。

複習一下,建構雜湊樹狀結構的一般演算法如下:

  1. 選擇隨機鹽 (十六進位編碼)。
  2. 將系統映像檔剖析為 4K 區塊。
  3. 取得每個區塊的 (加鹽) SHA256 雜湊。
  4. 串連這些雜湊以形成層級
  5. 將等級 0 到 4K 區塊邊界。
  6. 將層級與雜湊樹狀結構串連。
  7. 重複步驟 2 到 6,以前一個層級做為下一個步驟的來源,直到 只有一個雜湊值

完成後,系統會產生單一雜湊,也就是根雜湊。這和你的鹽分 用於建構 dm-verity 製圖表。

建構 dm-verity 對應表格

建立 dm-verity 對應表,用來識別區塊裝置 (或目標) 核心與雜湊樹狀結構的位置 (相同值)。這個 對應用於產生及啟動 fstab。表格也會列出 區塊大小和 hash_start,雜湊樹狀結構的開始位置 (具體來說,是從圖片開頭加上區塊編號)。

請參閱密碼設定以瞭解 錯誤目標對應資料表欄位的詳細說明。

簽署 dm-verity 資料表

簽署 dm-verity 資料表以產生資料表簽章。如要驗證 資料表簽章會先驗證資料表簽章這取決於 保存在固定位置的開機映像檔金鑰通常包含在 製造商可以建構系統,在 或 HTTP/HTTPS 位置

如何使用這個簽章和按鍵組合驗證分區:

  1. 將 libmincrypt 相容格式的 RSA-2048 金鑰加進 /boot 個分區 /verity_key。指出用於驗證的金鑰所在位置 雜湊樹狀結構
  2. 在相關項目的 fstab 中新增 verifyfs_mgr 旗標。

將資料表簽章整合至中繼資料

將資料表簽章和 dm-verity 資料表封裝為驗證狀態中繼資料。整個 中繼資料區塊不同,因此有可能會擴充,例如加入 或更改部分順序

做為例行性檢查,系統會在每組資料表中繼資料中,產生相關聯的魔法數字 以便識別資料表因為長度包含於 ext4 系統 這樣就能在不瞭解 資料本身的內容

這確保您未選擇驗證未經驗證的分區。如果是, 如果缺少這個魔法號碼,驗證程序就會終止。這個號碼 類似:
0xb001b001

十六進位的位元組值如下:

  • 第一個位元組 = b0
  • 位元組 = 01
  • 第三個位元組 = b0
  • 第四位元組 = 01

下圖說明具體中繼資料的細目:

<magic number>|<version>|<signature>|<table length>|<table>|<padding>
\-------------------------------------------------------------------/
\----------------------------------------------------------/   |
                            |                                  |
                            |                                 32K
                       block content

這份表格說明這些中繼資料欄位。

表 1. 詳細程度中繼資料欄位

欄位 目的 大小
魔法數字 用 fs_mgr 做為性質檢查 4 個位元組 0xb001b001
version 以便將中繼資料區塊 4 個位元組 目前為 0
簽名 PKCS1.5 填充形式的資料表簽章 256 個位元組
表格長度 dm-verity 資料表的長度 (以位元組為單位) 4 個位元組
桌子 請參閱前述的 dm-verity 表格 資料表長度位元組數
padding 這個結構的長度為 0 個,長度為 32K 0

最佳化 dm-verity

為了讓 dmverity 發揮最佳效能,你應該:

  • 在核心中,為 ARMv7 和 SHA-2 開啟 NEON SHA-2 適用於 ARMv8 的擴充功能
  • 測試不同的預先讀取和預先擷取叢集 即可找出最適合裝置的設定。