驗證啟動需要在使用之前以加密方式驗證作為正在啟動的 Android 版本一部分的所有可執行代碼和數據。這包括內核(從boot
分區加載)、設備樹(從dtbo
分區加載)、 system
分區、 vendor
分區等。
僅讀取一次的小分區(例如boot
和dtbo
)通常通過將整個內容加載到內存中然後計算其哈希來進行驗證。然後將該計算的哈希值與預期的哈希值進行比較。如果值不匹配,Android 將不會加載。有關更多詳細信息,請參閱引導流程。
不適合內存的較大分區(例如文件系統)可能會使用哈希樹,其中驗證是在數據加載到內存時發生的連續過程。在這種情況下,哈希樹的根哈希是在運行時計算的,並根據預期的根哈希值進行檢查。 Android 包含dm-verity 驅動程序來驗證更大的分區。如果在某些時候計算的根哈希值與預期的根哈希值不匹配,則不會使用數據並且 Android 會進入錯誤狀態。有關更多詳細信息,請參閱dm-verity 損壞。
預期的散列通常存儲在每個已驗證分區的末尾或開頭、專用分區或兩者中。至關重要的是,這些哈希是由信任根(直接或間接)簽名的。例如,AVB 實現支持這兩種方法,有關詳細信息,請參閱Android Verified Boot 。
回滾保護
即使使用完全安全的更新過程,非持久性 Android 內核漏洞也有可能手動安裝舊的、更易受攻擊的 Android 版本,重新啟動到易受攻擊的版本,然後使用該 Android 版本安裝持久性漏洞。攻擊者從那里永久擁有該設備並且可以做任何事情,包括禁用更新。
針對此類攻擊的保護稱為回滾保護。回滾保護通常通過使用防篡改存儲來記錄最新版本的 Android 並在低於記錄的版本時拒絕啟動 Android 來實現。版本通常在每個分區的基礎上進行跟踪。
有關 AVB 如何處理回滾保護的更多詳細信息,請參閱 AVB自述文件。
處理驗證錯誤
驗證可能在引導時失敗(例如,如果計算的boot
分區上的哈希與預期的哈希不匹配)或在運行時(例如,如果 dm-verity 在system
分區上遇到驗證錯誤)。如果啟動時驗證失敗,設備將無法啟動,最終用戶需要執行步驟來恢復設備。
如果驗證在運行時失敗,則流程會更複雜一些。如果設備使用 dm-verity,則應將其配置為restart
模式。在restart
模式下,如果遇到驗證錯誤,設備會立即重啟,並設置一個特定的標誌來指示原因。引導加載程序應該注意到這個標誌並切換 dm-verity 以使用 I/O 錯誤 ( eio
) 模式並保持在此模式直到安裝了新的更新。
在eio
模式下啟動時,設備會顯示錯誤屏幕,通知用戶已檢測到損壞並且設備可能無法正常運行。屏幕一直顯示,直到用戶關閉它。在eio
模式下,如果遇到驗證錯誤,dm-verity 驅動程序不會重新啟動設備,而是返回 EIO 錯誤,應用程序需要處理該錯誤。
目的是系統更新程序將運行(因此可以安裝沒有損壞錯誤的新操作系統)或者用戶可以從設備上獲取盡可能多的數據。安裝新操作系統後,引導加載程序會注意到新安裝的操作系統並切換回restart
模式。