Android 7.0 及更高版本支持基於文件的加密 (FBE)。基於文件的加密允許使用可以獨立解鎖的不同密鑰對不同文件進行加密。
本文介紹如何在新設備上啟用基於文件的加密,以及系統應用程序如何使用 Direct Boot API 為用戶提供最佳、最安全的體驗。
直接啟動
基於文件的加密啟用了 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 源代碼樹的 frameworks 或 packages 目錄中運行命令mangrep directBootAware
可以找到更多具有加密意識的應用程序和服務示例。
依賴項
為了安全地使用 FBE 的 AOSP 實現,設備需要滿足以下依賴關係:
- 內核支持Ext4 加密或 F2FS 加密。
- HAL 版本 1.0 或 2.0 的Keymaster 支持。不支持 Keymaster 0.3,因為它不提供必要的功能或確保對加密密鑰的充分保護。
- Keymaster/ Keystore和 Gatekeeper必須在可信執行環境(TEE) 中實施,以便為 DE 密鑰提供保護,以便未經授權的操作系統(閃存到設備上的自定義操作系統)不能簡單地請求 DE 密鑰。
- 需要綁定到 keymaster 初始化的硬件信任根和驗證啟動,以確保未經授權的操作系統無法訪問設備加密憑據。
注意:存儲策略適用於文件夾及其所有子文件夾。製造商應將未加密的內容限制在 OTA 文件夾和保存系統解密密鑰的文件夾中。大多數內容應駐留在憑證加密存儲中,而不是設備加密存儲中。
執行
首先,根據Direct Boot開發者文檔,鬧鐘、電話、輔助功能等應用程序應設為 android:directBootAware。
內核支持
對 Ext4 和 F2FS 加密的內核支持在 Android 通用內核 3.18 及更高版本中可用。要在 5.1 或更高版本的內核中啟用它,請使用:
CONFIG_FS_ENCRYPTION=y
對於較舊的內核,如果設備的用戶數據文件系統是 Ext4,則使用CONFIG_EXT4_ENCRYPTION=y
,如果設備的userdata
數據文件系統是userdata
,則使用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-cts
如果contents_encryption_mode
是aes-256-xts
或adiantum
如果contents_encryption_mode
是adiantum
。 - Android 11 中新增的
flags
參數是由+
字符分隔的標誌列表。支持以下標誌:-
v1
標誌選擇版本 1 加密策略;v2
標誌選擇版本 2 加密策略。第 2 版加密策略使用更安全、更靈活的密鑰派生功能。如果設備在 Android 11 或更高版本上啟動(由ro.product.first_api_level
確定),則默認值為 v2,如果設備在 Android 10 或更低版本上啟動,則默認值為 v1。 -
inlinecrypt_optimized
標誌選擇一種加密格式,該格式針對不能有效處理大量密鑰的內聯加密硬件進行了優化。它通過每個 CE 或 DE 密鑰僅派生一個文件內容加密密鑰來實現這一點,而不是每個文件一個。 IVs(初始化向量)的生成會相應調整。 -
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 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 集成
密鑰的生成和內核密鑰環的管理由vold
處理。 FBE 的 AOSP 實現要求設備支持 Keymaster HAL 1.0 或更高版本。不支持早期版本的 Keymaster HAL。
首次啟動時,會在啟動過程的早期生成並安裝用戶 0 的密鑰。當init
的on-post-fs
階段完成時,Keymaster 必須準備好處理請求。在 Pixel 設備上,這是通過一個腳本塊來處理的,確保 Keymaster 在掛載/data
之前啟動。
加密策略
基於文件的加密在目錄級別應用加密策略。首次創建設備的用戶數據分區時, userdata
腳本init
應用基本結構和策略。這些腳本將觸發創建第一個用戶(用戶 0)的 CE 和 DE 密鑰,並定義哪些目錄將使用這些密鑰進行加密。當創建其他用戶和配置文件時,會生成必要的附加密鑰並將其存儲在密鑰庫中;他們的憑證和設備存儲位置被創建,加密策略將這些密鑰鏈接到這些目錄。
在 Android 11 及更高版本中,加密策略不再硬編碼到集中位置,而是由 init 腳本中mkdir
命令的參數定義。使用系統 DE 密鑰加密的目錄使用encryption=Require
,而未加密的目錄(或其子目錄使用每個用戶密鑰加密的目錄)使用encryption=None
。
在 Android 10 中,加密策略被硬編碼到這個位置:
/system/extras/libfscrypt/fscrypt_init_extensions.cpp
在 Android 9 及更早版本中,該位置為:
/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp
可以添加例外以防止某些目錄被加密。如果進行了此類修改,則設備製造商應包含SELinux 策略,僅授予對需要使用未加密目錄的應用程序的訪問權限。這應該排除所有不受信任的應用程序。
唯一已知的可接受的用例是支持舊版 OTA 功能。
在系統應用程序中支持直接啟動
使應用程序具有 Direct Boot 意識
為了方便系統應用程序的快速遷移,可以在應用程序級別設置兩個新屬性。 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 的更多信息,請參閱上游內核文檔。
密鑰派生
基於文件的加密密鑰是 512 位密鑰,由 TEE 中保存的另一個密鑰(256 位 AES-GCM 密鑰)加密存儲。要使用此 TEE 密鑰,必須滿足三個要求:
- 授權令牌
- 延伸的憑證
- “可丟棄的哈希”
身份驗證令牌是用戶成功登錄時由Gatekeeper生成的加密身份驗證令牌。除非提供正確的身份驗證令牌,否則 TEE 將拒絕使用該密鑰。如果用戶沒有憑證,則不需要使用授權令牌。
拉伸憑證是使用scrypt
算法加鹽拉伸後的用戶憑證。在傳遞給vold
以傳遞給scrypt
之前,憑據實際上在鎖定設置服務中被散列一次。這以加密方式綁定到 TEE 中的密鑰,並具有適用於KM_TAG_APPLICATION_ID
的所有保證。如果用戶沒有憑證,則不使用也不需要擴展憑證。
secdiscardable hash
是隨機 16 KB 文件的 512 位散列,與用於重建密鑰的其他信息(例如種子)一起存儲。該文件在刪除密鑰時被安全刪除,或者以新的方式加密;這種額外的保護確保攻擊者必須恢復這個安全刪除的文件的每一位以恢復密鑰。這以加密方式綁定到 TEE 中的密鑰,並具有適用於KM_TAG_APPLICATION_ID
的所有保證。
在大多數情況下,FBE 密鑰還在內核中經過額外的密鑰派生步驟,以生成實際用於進行加密的子密鑰,例如每個文件或每個模式的密鑰。對於版本 2 加密策略,使用 HKDF-SHA512。