Android 7.0 及更高版本支持基於文件的加密 (FBE)。基於文件的加密允許使用不同的密鑰對不同的文件進行加密,這些密鑰可以獨立解鎖。
本文介紹如何在新設備上啟用基於文件的加密,以及系統應用程序如何使用直接啟動 API 為用戶提供最佳、最安全的體驗。
所有搭載 Android 10 及更高版本的設備都需要使用基於文件的加密。
直接啟動
基於文件的加密啟用了 Android 7.0 中引入的一項名為Direct Boot的新功能。直接啟動允許加密設備直接啟動到鎖定屏幕。以前,在使用全盤加密(FDE) 的加密設備上,用戶需要提供憑據才能訪問任何數據,這會阻止手機執行除最基本操作以外的所有操作。例如,警報無法運行,無障礙服務不可用,電話無法接聽電話,但僅限於基本的緊急撥號操作。
隨著基於文件的加密 (FBE) 和新 API 的引入,使應用程序意識到加密,這些應用程序可以在有限的上下文中運行。這可能發生在用戶提供他們的憑據之前,同時仍然保護私人用戶信息。
在支持 FBE 的設備上,設備的每個用戶都有兩個可供應用程序使用的存儲位置:
- 憑據加密 (CE) 存儲,這是默認存儲位置,僅在用戶解鎖設備後可用。
- 設備加密 (DE) 存儲,這是在直接啟動模式期間和用戶解鎖設備後都可用的存儲位置。
這種分離使工作配置文件更加安全,因為它允許同時保護多個用戶,因為加密不再僅基於啟動時密碼。
Direct Boot API 允許加密感知應用程序訪問這些區域中的每一個。應用程序生命週期發生了一些變化,以適應在用戶的 CE 存儲被解鎖以響應在鎖定屏幕上首次輸入憑據時通知應用程序的需要,或者在工作配置文件提供工作挑戰的情況下。運行 Android 7.0 的設備必須支持這些新的 API 和生命週期,無論它們是否實現 FBE。雖然,如果沒有 FBE,DE 和 CE 存儲將始終處於解鎖狀態。
Android 開源項目 (AOSP) 中提供了 Ext4 和 F2FS 文件系統上基於文件的加密的完整實現,並且只需要在滿足要求的設備上啟用。選擇使用 FBE 的製造商可能希望根據所使用的片上系統 (SoC) 探索優化功能的方法。
AOSP 中所有必要的包都已更新為支持直接啟動。但是,如果設備製造商使用這些應用程序的定製版本,他們將希望至少確保有直接啟動感知包提供以下服務:
- 電話服務和撥號器
- 鎖屏密碼輸入法
示例和來源
Android 提供了文件加密的參考實現,其中 vold( system/vold )提供了在 Android 上管理存儲設備和卷的功能。 FBE 的添加為 vold 提供了幾個新命令以支持對多個用戶的 CE 和 DE 密鑰進行密鑰管理。除了在內核中使用基於文件的加密功能的核心更改外,還修改了許多系統包,包括鎖屏和 SystemUI 以支持 FBE 和直接啟動功能。這些包括:
- AOSP 撥號器(包/應用程序/撥號器)
- 桌面時鐘(包/應用程序/DeskClock)
- LatinIME(包/輸入法/LatinIME)*
- 設置應用程序(包/應用程序/設置)*
- SystemUI(框架/基礎/包/SystemUI)*
* 使用defaultToDeviceProtectedStorage
清單屬性的系統應用程序
通過在 AOSP 源代碼樹的框架或包目錄中運行命令mangrep directBootAware
可以找到更多加密感知的應用程序和服務示例。
依賴關係
要安全地使用 FBE 的 AOSP 實現,設備需要滿足以下依賴項:
- 內核支持Ext4 加密或 F2FS 加密。
- Keymaster 支持HAL 版本 1.0 或更高版本。不支持 Keymaster 0.3,因為它不提供必要的功能或確保對加密密鑰的充分保護。
- Keymaster/ Keystore和 Gatekeeper必須在可信執行環境(TEE) 中實施,以便為 DE 密鑰提供保護,以便未經授權的操作系統(自定義操作系統閃存到設備上)不能簡單地請求 DE 密鑰。
- 需要綁定到 Keymaster 初始化的硬件信任根和驗證啟動,以確保未經授權的操作系統無法訪問 DE 密鑰。
執行
首先,根據直接啟動開發人員文檔,鬧鐘、電話和輔助功能等應用程序應設為 android:directBootAware。
內核支持
Android 通用內核版本 3.18 及更高版本提供了對 Ext4 和 F2FS 加密的內核支持。要在 5.1 或更高版本的內核中啟用它,請使用:
CONFIG_FS_ENCRYPTION=y
對於較舊的內核,如果您的設備的用戶userdata
文件系統是 Ext4,則使用 CONFIG_EXT4_ENCRYPTION CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_EXT4_ENCRYPTION=y
或者如果您的設備的用戶userdata
文件系統是 F2FS,則使用 CONFIG_F2FS_FS_ENCRYPTION=y。
如果您的設備將支持可採用的存儲或將在內部存儲上使用元數據加密,還請啟用元數據加密所需的內核配置選項,如元數據加密文檔中所述。
除了對 Ext4 或 F2FS 加密的功能支持外,設備製造商還應啟用加密加速以加速基於文件的加密並改善用戶體驗。例如,在基於 ARM64 的設備上,可以通過設置以下內核配置選項來啟用 ARMv8 CE(加密擴展)加速:
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_SHA2_ARM64_CE=y
為了進一步提高性能並降低功耗,設備製造商還可以考慮實施內聯加密硬件,它可以在數據進出存儲設備的途中對數據進行加密/解密。 Android 通用內核(4.14 版及更高版本)包含一個框架,允許在硬件和供應商驅動程序支持可用時使用內聯加密。可以通過設置以下內核配置選項來啟用內聯加密框架:
CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_FS_ENCRYPTION=y CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
如果您的設備使用基於 UFS 的存儲,還啟用:
CONFIG_SCSI_UFS_CRYPTO=y
如果您的設備使用基於 eMMC 的存儲,還啟用:
CONFIG_MMC_CRYPTO=y
啟用基於文件的加密
在設備上啟用 FBE 需要在內部存儲 ( userdata
) 上啟用它。這也會自動在可採用的存儲上啟用 FBE;但是,如有必要,可採用的存儲上的加密格式可能會被覆蓋。
內部存儲器
通過將選項fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]]
添加到userdata
的fstab
行的fs_mgr_flags列來啟用 FBE。此選項定義內部存儲的加密格式。它最多包含三個以冒號分隔的參數:
-
contents_encryption_mode
參數定義了使用哪種加密算法來加密文件內容。它可以是aes-256-xts
或adiantum
。從 Android 11 開始,它也可以留空以指定默認算法,即aes-256-xts
。 -
filenames_encryption_mode
參數定義了使用哪種加密算法來加密文件名。它可以是aes-256-cts
、aes-256-heh
、adiantum
或aes-256-hctr2
。如果未指定,則默認為aes-256-cts
如果contents_encryption_mode
是aes-256-xts
,或者默認為adiantum
如果contents_encryption_mode
是adiantum
。 -
flags
參數是 Android 11 中的新參數,它是由+
字符分隔的標誌列表。支持以下標誌:-
v1
標誌選擇版本 1 加密策略;v2
標誌選擇版本 2 加密策略。第 2 版加密策略使用更安全、更靈活的密鑰派生函數。如果設備在 Android 11 或更高版本上啟動(由ro.product.first_api_level
確定),則默認值為 v2;如果設備在 Android 10 或更低版本上啟動,則默認值為 v1。 -
inlinecrypt_optimized
標誌選擇一種加密格式,該格式針對不能有效處理大量密鑰的內聯加密硬件進行了優化。它通過為每個 CE 或 DE 密鑰派生一個文件內容加密密鑰,而不是為每個文件派生一個來實現這一點。 IV(初始化向量)的生成相應地進行了調整。 -
emmc_optimized
標誌類似於inlinecrypt_optimized
,但它還選擇了一種將 IV 限制為 32 位的 IV 生成方法。此標誌只能用於符合 JEDEC eMMC v5.2 規範的內聯加密硬件,因此僅支持 32 位 IV。在其他內聯加密硬件上,請改用inlinecrypt_optimized
。這個標誌不應該用在基於 UFS 的存儲上; UFS 規範允許使用 64 位 IV。 - 在支持硬件封裝密鑰的設備上,
wrappedkey_v0
標誌允許對 FBE 使用硬件封裝密鑰。這只能與inlinecrypt
掛載選項以及inlinecrypt_optimized
或emmc_optimized
標誌結合使用。
-
如果您不使用內聯加密硬件,則大多數設備的推薦設置是fileencryption=aes-256-xts
。如果您使用的是內聯加密硬件,大多數設備的推薦設置是fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized
(或等效的fileencryption=::inlinecrypt_optimized
)。在沒有任何形式的 AES 加速的設備上,可以通過設置fileencryption=adiantum
使用Adiantum代替 AES。
自 Android 14(AOSP 實驗性)以來,AES-HCTR2 是具有加速加密指令的設備的首選文件名加密模式。但是,只有較新的 Android 內核支持 AES-HCTR2。在未來的 Android 版本中,它計劃成為文件名加密的默認模式。如果您的內核支持 AES-HCTR2,則可以通過將filenames_encryption_mode
設置為aes-256-hctr2
來啟用文件名加密。在最簡單的情況下,這將通過fileencryption=aes-256-xts:aes-256-hctr2
完成。
在搭載 Android 10 或更低版本的設備上,還接受fileencryption=ice
以指定使用FSCRYPT_MODE_PRIVATE
文件內容加密模式。此模式未由 Android 通用內核實現,但可以由供應商使用自定義內核補丁實現。這種模式產生的磁盤格式是特定於供應商的。在搭載 Android 11 或更高版本的設備上,不再允許使用此模式,必須改用標準加密格式。
默認情況下,文件內容加密是使用 Linux 內核的加密 API 完成的。如果您想改用內聯加密硬件,還可以添加inlinecrypt
掛載選項。例如,完整的fstab
行可能如下所示:
/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized
可採用的存儲
從 Android 9 開始,FBE 和可用存儲可以一起使用。
為userdata
指定fileencryption
fstab 選項也會自動在可採用的存儲上啟用 FBE 和元數據加密。但是,您可以通過在PRODUCT_PROPERTY_OVERRIDES
中設置屬性來覆蓋可採用存儲上的 FBE 和/或元數據加密格式。
在搭載 Android 11 或更高版本的設備上,使用以下屬性:
-
ro.crypto.volume.options
(Android 11 中的新功能)選擇可採用的存儲上的 FBE 加密格式。它與fileencryption
fstab 選項的參數具有相同的語法,並且使用相同的默認值。請參閱上面的fileencryption
建議,了解此處使用的內容。 -
ro.crypto.volume.metadata.encryption
選擇可採用的存儲上的元數據加密格式。請參閱元數據加密文檔。
在搭載 Android 10 或更低版本的設備上,使用以下屬性:
-
ro.crypto.volume.contents_mode
選擇內容加密模式。這相當於ro.crypto.volume.options
的第一個冒號分隔字段。 -
ro.crypto.volume.filenames_mode
選擇文件名加密模式。這等同於ro.crypto.volume.options
的第二個以冒號分隔的字段,除了搭載 Android 10 或更低版本的設備上的默認值為aes-256-heh
。在大多數設備上,這需要明確地覆蓋為aes-256-cts
。 -
ro.crypto.fde_algorithm
和ro.crypto.fde_sector_size
選擇可採用的存儲上的元數據加密格式。請參閱元數據加密文檔。
與 Keymaster 集成
Keymaster HAL 應作為early_hal
類的一部分啟動。這是因為 FBE 要求 Keymaster 準備好在post-fs-data
啟動階段處理請求,這是vold
設置初始密鑰的時間。
排除目錄
init
將系統 DE 密鑰應用於/data
的所有頂級目錄,但必須未加密的目錄除外:包含系統 DE 密鑰本身的目錄,以及包含用戶 CE 或 DE 目錄的目錄。加密密鑰遞歸應用,不能被子目錄覆蓋。
在 Android 11 及更高版本中, init
應用於目錄的密鑰可以通過 init 腳本中mkdir
命令的encryption=<action>
參數來控制。 <action>
的可能值記錄在Android 初始化語言的自述文件中。
在 Android 10 中, init
加密操作被硬編碼到以下位置:
/system/extras/libfscrypt/fscrypt_init_extensions.cpp
在 Android 9 及更早版本中,位置為:
/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp
可以添加例外以完全防止某些目錄被加密。如果進行此類修改,則設備製造商應包含SELinux 策略,該策略僅授予對需要使用未加密目錄的應用程序的訪問權限。這應該排除所有不受信任的應用程序。
唯一已知的可接受用例是支持傳統的 OTA 功能。
在系統應用程序中支持直接啟動
使應用程序直接啟動感知
為了方便系統應用的快速遷移,有兩個新的屬性可以在應用層進行設置。 defaultToDeviceProtectedStorage
屬性僅適用於系統應用程序。 directBootAware
屬性對所有人可用。
<application android:directBootAware="true" android:defaultToDeviceProtectedStorage="true">
應用程序級別的directBootAware
屬性是將應用程序中的所有組件標記為加密感知的簡寫。
defaultToDeviceProtectedStorage
屬性將默認應用存儲位置重定向為指向 DE 存儲,而不是指向 CE 存儲。使用此標誌的系統應用程序必須仔細審核存儲在默認位置的所有數據,並將敏感數據的路徑更改為使用 CE 存儲。使用此選項的設備製造商應仔細檢查他們存儲的數據,以確保其中不包含任何個人信息。
以這種模式運行時,以下系統 API 可用於在需要時顯式管理由 CE 存儲支持的上下文,這相當於它們的受設備保護的對應部分。
-
Context.createCredentialProtectedStorageContext()
-
Context.isCredentialProtectedStorage()
支持多用戶
多用戶環境中的每個用戶都獲得一個單獨的加密密鑰。每個用戶都會獲得兩個密鑰:一個 DE 密鑰和一個 CE 密鑰。用戶 0 必須先登錄設備,因為它是特殊用戶。這與設備管理用途有關。
加密感知應用程序以這種方式跨用戶交互: INTERACT_ACROSS_USERS
和INTERACT_ACROSS_USERS_FULL
允許應用程序跨設備上的所有用戶進行操作。但是,這些應用程序將只能訪問已解鎖用戶的 CE 加密目錄。
應用程序可能能夠跨 DE 區域自由交互,但解鎖一個用戶並不意味著設備上的所有用戶都解鎖。應用程序應在嘗試訪問這些區域之前檢查此狀態。
每個工作配置文件用戶 ID 也有兩個密鑰:DE 和 CE。當遇到工作挑戰時,配置文件用戶將被解鎖,Keymaster(在 TEE 中)可以提供配置文件的 TEE 密鑰。
處理更新
恢復分區無法訪問用戶數據分區上的 DE 保護存儲。強烈建議實施 FBE 的設備支持使用A/B 系統更新的OTA。由於可以在正常操作期間應用 OTA,因此無需恢復即可訪問加密驅動器上的數據。
使用舊版 OTA 解決方案時,需要恢復才能訪問userdata
分區上的 OTA 文件:
- 在
userdata
分區中創建一個頂級目錄(例如misc_ne
)。 - 將此頂級目錄配置為未加密(請參閱排除目錄)。
- 在頂級目錄中創建一個目錄來保存 OTA 包。
- 添加 SELinux 規則和文件上下文以控制對此目錄及其內容的訪問。只有接收 OTA 更新的進程或應用程序才能讀取和寫入此目錄。任何其他應用程序或進程都不應訪問此目錄。
驗證
為確保該功能的實施版本按預期工作,首先運行許多 CTS 加密測試,例如DirectBootHostTest和EncryptionTest 。
如果設備運行的是 Android 11 或更高版本,還要運行vts_kernel_encryption_test :
atest vts_kernel_encryption_test
或者:
vts-tradefed run vts -m vts_kernel_encryption_test
此外,設備製造商可能會執行以下手動測試。在啟用了 FBE 的設備上:
- 檢查
ro.crypto.state
是否存在- 確保
ro.crypto.state
已加密
- 確保
- 檢查
ro.crypto.type
是否存在- 確保
ro.crypto.type
設置為file
- 確保
此外,測試人員可以在主用戶上設置鎖屏來啟動userdebug
實例。然後adb
shell 進入設備並使用su
成為 root。確保/data/data
包含加密的文件名;如果沒有,則有問題。
還鼓勵設備製造商探索在其設備或內核上運行fscrypt 的上游 Linux 測試。這些測試是 xfstests 文件系統測試套件的一部分。然而,這些上游測試並沒有被 Android 官方支持。
AOSP 實現細節
本部分提供有關 AOSP 實現的詳細信息,並描述基於文件的加密的工作原理。設備製造商無需在此處進行任何更改即可在其設備上使用 FBE 和直接啟動。
fscrypt加密
AOSP 實現在內核中使用“fscrypt”加密(由 ext4 和 f2fs 支持),通常配置為:
- 在 XTS 模式下使用 AES-256 加密文件內容
- 在 CBC-CTS 模式下使用 AES-256 加密文件名
還支持Adiantum 加密。當啟用 Adiantum 加密時,文件內容和文件名都使用 Adiantum 加密。
fscrypt 支持兩個版本的加密策略:版本 1 和版本 2。版本 1 已棄用,搭載 Android 11 及更高版本的設備的 CDD 要求僅兼容版本 2。版本 2 加密策略使用HKDF-SHA512推導實際來自用戶空間提供的密鑰的加密密鑰。
有關 fscrypt 的更多信息,請參閱上游內核文檔。
存儲類
下表更詳細地列出了 FBE 密鑰及其保護的目錄:
存儲類 | 描述 | 目錄 |
---|---|---|
系統DE | 設備加密數據不綁定到特定用戶 | /data/system 、 /data/app 和/data 的各種其他子目錄 |
每次引導 | 不需要在重啟後繼續存在的臨時系統文件 | /data/per_boot |
用戶 CE(內部) | 內部存儲上的每用戶憑據加密數據 |
|
用戶 DE(內部) | 內部存儲上的每用戶設備加密數據 |
|
用戶CE(可採用) | 可採用存儲上的每用戶憑據加密數據 |
|
用戶DE(可採用) | 可採用存儲上的按用戶設備加密的數據 |
|
密鑰存儲和保護
所有 FBE 密鑰都由vold
管理,並加密存儲在磁盤上,除了完全不存儲的每次啟動密鑰。下表列出了各種 FBE 密鑰的存儲位置:
按鍵類型 | 鑰匙位置 | 關鍵位置的存儲類 |
---|---|---|
系統DE密鑰 | /data/unencrypted | 未加密 |
用戶 CE(內部)密鑰 | /data/misc/vold/user_keys/ce/${user_id} | 系統DE |
用戶 DE(內部)密鑰 | /data/misc/vold/user_keys/de/${user_id} | 系統DE |
用戶 CE(可採用)密鑰 | /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} | 用戶 CE(內部) |
用戶 DE(可採用)密鑰 | /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} | 用戶 DE(內部) |
如上表所示,大多數 FBE 密鑰存儲在由另一個 FBE 密鑰加密的目錄中。在解鎖包含密鑰的存儲類之前,無法解鎖密鑰。
vold
還對所有 FBE 密鑰應用一層加密。除了用於內部存儲的 CE 密鑰之外,每個密鑰都使用 AES-256-GCM 使用其自己的密鑰庫密鑰進行加密,該密鑰不會暴露在 TEE 之外。這確保 FBE 密鑰無法解鎖,除非已啟動受信任的操作系統,如Verified Boot所強制執行的那樣。 Keystore 密鑰也請求回滾阻力,這允許在 Keymaster 支持回滾阻力的設備上安全地刪除 FBE 密鑰。作為回滾阻力不可用時的最大努力回退,存儲在與密鑰一起存儲的secdiscardable
文件中的 16384 個隨機字節的 SHA-512 哈希被用作密鑰庫密鑰的應用程序 ID 標籤。需要恢復所有這些字節以恢復 FBE 密鑰。
用於內部存儲的 CE 密鑰獲得更高級別的保護,確保在不知道用戶的鎖屏知識因素 (LSKF) (PIN、圖案或密碼)、安全密碼重置令牌或客戶端兩者的情況下無法解鎖它們和用於Resume-on-Reboot操作的服務器端密鑰。僅允許為工作配置文件和完全託管設備創建密碼重置令牌。
為實現這一點, vold
使用從用戶合成密碼派生的 AES-256-GCM 密鑰對內部存儲的每個 CE 密鑰進行加密。合成密碼是為每個用戶隨機生成的不可變的高熵密碼秘密。 system_server
中的LockSettingsService
管理合成密碼及其保護方式。
為了使用 LSKF 保護合成密碼, LockSettingsService
首先通過scrypt
傳遞 LSKF 來拉伸 LSKF,目標時間約為 25 毫秒,內存使用量約為 2 MiB。由於 LSKF 通常很短,因此這一步通常不會提供太多安全性。主要的安全層是安全元件 (SE)或 TEE 強制執行的速率限制,如下所述。
如果設備具有安全元件 (SE),則LockSettingsService
使用Weaver HAL將擴展的 LSKF 映射到存儲在 SE 中的高熵隨機秘密。 LockSettingsService
然後對合成密碼進行兩次加密:第一次使用從擴展 LSKF 和 Weaver 秘密派生的軟件密鑰,第二次使用非授權綁定密鑰庫密鑰。這提供了 LSKF 猜測的 SE 強制速率限制。
如果設備沒有 SE,則LockSettingsService
會使用擴展的 LSKF 作為網守密碼。 LockSettingsService
然後對合成密碼進行兩次加密:第一次是使用從擴展 LSKF 派生的軟件密鑰和 secdiscardable 文件的哈希,第二次是使用授權綁定到 Gatekeeper 註冊的 Keystore 密鑰。這提供了 LSKF 猜測的 TEE 強制速率限制。
當 LSKF 更改時, LockSettingsService
刪除所有與合成密碼綁定到舊 LSKF 相關的信息。在支持 Weaver 或抗回滾密鑰庫密鑰的設備上,這保證了舊綁定的安全刪除。因此,即使用戶沒有 LSKF,此處描述的保護也適用。