Android 4.4 以上版本支援驗證開機程序,可選擇是否啟用 device-mapper-verity (dm-verity) 核心功能 以及對區塊裝置的完整性檢查。dm-verity 有助於防止永久的 Rootkit 可能持有 Root 權限,進而入侵裝置這項功能可協助 Android 使用者確保裝置在啟動時,處於與上次使用時相同的狀態。
具有 root 權限的可能有害應用程式 (PHA) 可以隱藏在偵測程式中,或以其他方式遮蔽自己。根層級軟體可以 這通常比偵測工具更高的權限 「謊言」偵測程式
您可以使用 dm-verity 功能查看區塊裝置 (檔案系統的基礎儲存層),並判斷該裝置是否符合預期的設定。這項作業會使用加密編譯雜湊樹狀結構。每個區塊 (通常為 4k) 都有一個 SHA256 雜湊。
雜湊值儲存在網頁的樹狀結構中,因此只有頂層 「根」雜湊必須受到信任,才能驗證樹狀結構的其餘部分。Google Cloud 可以 修改任何區塊就等同於破壞加密編譯雜湊。 請參閱下圖,瞭解這個結構。
開機分割區包含公開金鑰,必須由裝置製造商在外部驗證。這組金鑰的用途是驗證簽章 並確認裝置的系統分區已受到保護 不變。
作業
dm-verity 防護機制位於核心中。因此,如果根目錄軟體在核心啟動前危害系統,就會保留該存取權。為降低這類風險,大多數製造商都會使用燒錄在裝置中的金鑰來驗證核心。裝置出廠後即無法變更車鑰。
製造商會使用該金鑰驗證第一層 Bootloader 的簽名,而 Bootloader 會依序驗證後續層級的簽名、應用程式 Bootloader,最後是核心。每家希望利用驗證開機程序的製造商,都應具備驗證核心完整性的方法。假設核心已完成驗證,核心可以查看區塊裝置,並在掛載時驗證。
驗證區塊裝置的方法之一,是直接對其內容進行雜湊運算,並與儲存的值進行比較。不過,嘗試驗證整個區塊裝置可能需要較長的時間,並耗用大量裝置電力。裝置 因此應用程式在使用前會大量消耗
相反地,dm-verity 會個別驗證區塊,且只在存取每個區塊時驗證。讀入記憶體時,系統會並行處理區塊的雜湊運算。雜湊為 完成樹狀結構的驗證後既然閱讀方塊是相當昂貴的 這項區塊層級驗證作業產生的延遲 也具有相對的名詞
如果驗證失敗,裝置會產生指出封鎖的 I/O 錯誤 無法讀取或無法讀取的內容系統會顯示檔案系統已損毀,這也是預期的結果。
應用程式可選擇在沒有結果資料的情況下繼續操作,例如 這些結果不一定適用於應用程式的主要功能。不過 如果應用程式無法在沒有資料的情況下繼續作業,就會失敗。
前向錯誤修正
Android 7.0 以上版本會使用前向錯誤修正 (FEC) 改善 dm-verity 的健全性。實作 Android 開放原始碼計畫時,我們會以 Reed-Solomon 錯誤修正程式碼,並套用 稱為「交錯」可減少空間負擔 可以復原的毀損區塊數量。如要進一步瞭解 FEC,請參閱「嚴格執行驗證開機程序並修正錯誤」。實作
摘要
- 產生 ext4 系統映像檔。
- 為圖片產生雜湊樹。
- 為該雜湊樹建立 dm-verity 表。
- 簽署該 dm-verity 資料表,以產生資料表簽署。
- 將資料表簽章和 dm-verity 表格整合到 verity 中繼資料中。
- 連結系統映像檔、verity 中繼資料和雜湊樹狀結構。
請參閱 Chromium 專案 - 驗證開機程序 ,取得雜湊樹狀結構和 dm-verity 資料表的詳細說明。
產生雜湊樹狀結構
如前文所述,雜湊樹是 dm-verity 不可或缺的一環。cryptsetup 工具會為您產生雜湊樹狀圖。或者,您也可以在下方定義相容的值:
<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
如果圖層中的區塊無法由上一個圖層的雜湊值自然填滿,您應以零填充,以達到預期的 4k。這樣一來,您就能知道雜湊樹並未遭到移除,而是以空白資料填入。
如要產生雜湊樹狀結構,請將第 2 層雜湊連結至第 1 層,將第 3 層雜湊連結至第 2 層,依此類推。將所有內容寫入磁碟。請注意,這不會參照根雜湊的 0 層。
回顧一下,建構雜湊樹狀結構的一般演算法如下:
- 選擇隨機鹽 (十六進位編碼)。
- 將系統映像檔解密為 4k 區塊。
- 取得每個區塊的 (加鹽) SHA256 雜湊。
- 將這些雜湊連接起來,形成一個層級
- 用 0s 到 4K 區塊邊界的版面。
- 將層級連結至雜湊樹狀圖。
- 重複步驟 2 到 6,以前一個層級做為下一個步驟的來源,直到 只有一個雜湊值
完成後,系統會產生單一雜湊,也就是根雜湊。這和你的鹽分 用於建構 dm-verity 製圖表。
建構 dm-verity 對應資料表
建立 dm-verity 對應表,用於識別核心的區塊裝置 (或目標) 和雜湊樹位置 (相同的值)。這個
對應用於產生及啟動 fstab
。表格也會列出
區塊大小和 hash_start,雜湊樹狀結構的開始位置
(具體來說,是從圖片開頭加上區塊編號)。
請參閱密碼設定以瞭解 錯誤目標對應資料表欄位的詳細說明。
簽署 dm-verity 資料表
簽署 dm-verity 資料表,產生資料表簽名。驗證分割區時,系統會先驗證資料表簽章。這取決於 保存在固定位置的開機映像檔製造商的建構系統通常會納入金鑰,以便在裝置上自動納入固定位置。
如要使用此簽名和金鑰組合驗證分區,請按照下列步驟操作:
- 將 libmincrypt 相容格式的 RSA-2048 金鑰加進
/boot
個分區/verity_key
。找出用來驗證雜湊樹狀結構的金鑰位置。 - 在相關項目的 fstab 中,將
verify
新增至fs_mgr
標記。
將資料表簽章封裝至中繼資料
將資料表簽名和 dm-verity 表格合併至 verity 中繼資料。整個 中繼資料區塊不同,因此有可能會擴充,例如加入 或更改部分順序
做為例行性檢查,系統會在每組資料表中繼資料中,產生相關聯的魔法數字 以便識別資料表由於長度已包含在 ext4 系統映像檔標頭中,因此您可以透過這種方式搜尋中繼資料,而無須知道資料本身的內容。
這務必確認您並未選擇驗證未經驗證的分區。如果是這種情況,缺少這個魔法數字就會導致驗證程序停止。這個數字與
0xb001b001
。
十六進位的位元組值如下:
- 第一個位元組 = b0
- 位元組 = 01
- 第三個位元組 = b0
- 第四位元組 = 01
下圖顯示 verity 中繼資料的細目:
<magic number>|<version>|<signature>|<table length>|<table>|<padding> \-------------------------------------------------------------------/ \----------------------------------------------------------/ | | | | 32K block content
下表說明這些中繼資料欄位。
欄位 | 目的 | 大小 | 值 |
---|---|---|---|
魔幻數字 | 用 fs_mgr 做為性質檢查 | 4 個位元組 | 0xb001b001 |
version | 以便將中繼資料區塊 | 4 個位元組 | 目前為 0 |
簽名 | PKCS1.5 填充形式的資料表簽章 | 256 個位元組 | |
表格長度 | dm-verity 資料表的長度 (以位元組為單位) | 4 個位元組 | |
桌子 | 先前所述的 dm-verity 表 | 資料表長度位元組數 | |
padding | 這個結構體會以 0 填補至 32k 長度 | 0 |
最佳化 dm-verity
如要讓 dm-verity 發揮最佳效能,請務必:
- 在核心中,為 ARMv7 和 SHA-2 開啟 NEON SHA-2 適用於 ARMv8 的擴充功能
- 嘗試使用不同的預讀和 prefetch_cluster 設定,找出最適合裝置的最佳設定。