Android 7.0 及更高版本支持基於文件的加密 (FBE)。基於文件的加密允許使用不同的密鑰對不同的文件進行加密,這些密鑰可以獨立解鎖。
本文介紹如何在新設備上啟用基於文件的加密,以及系統應用程序如何使用直接啟動 API 為用戶提供最佳、最安全的體驗。
所有搭載 Android 10 及更高版本的設備都需要使用基於文件的加密。
直接啟動
基於文件的加密啟用了 Android 7.0 中引入的一項稱為“直接啟動”的新功能。直接啟動允許加密設備直接啟動至鎖定屏幕。以前,在使用全盤加密(FDE) 的加密設備上,用戶需要提供憑據才能訪問任何數據,從而導致手機無法執行除最基本的操作之外的所有操作。例如,警報無法運行,無障礙服務無法使用,電話無法接聽電話,但僅限於基本的緊急撥號器操作。
隨著基於文件的加密 (FBE) 和新 API 的引入,使應用程序能夠感知加密,這些應用程序可以在有限的上下文中運行。這可能發生在用戶提供憑據之前,同時仍然保護私人用戶信息。
在啟用 FBE 的設備上,設備的每個用戶都有兩個可供應用程序使用的存儲位置:
- 憑證加密 (CE) 存儲,這是默認存儲位置,僅在用戶解鎖設備後才可用。
- 設備加密 (DE) 存儲,這是在直接啟動模式期間和用戶解鎖設備後都可用的存儲位置。
這種分離使工作配置文件更加安全,因為加密不再僅基於啟動時密碼,因此一次可以保護多個用戶。
直接啟動 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=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
。如果未指定,則如果contents_encryption_mode
為aes-256-cts
,則默認為aes-256-xts
;如果contents_encryption_mode
為adiantum
,則默認為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 init language 的 README中。
在 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 進行加密。
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 密鑰。 Keystore 密鑰還要求具有回滾阻力,這樣可以在 Keymaster 支持回滾阻力的設備上安全地刪除 FBE 密鑰。作為回滾阻力不可用時的盡力後備,存儲在與密鑰一起存儲的secdiscardable
文件中的 16384 個隨機字節的 SHA-512 哈希值用作密鑰庫密鑰的應用程序 ID 標記。需要恢復所有這些字節才能恢復 FBE 密鑰。
用於內部存儲的 CE 密鑰獲得更強級別的保護,確保在不知道用戶的鎖屏知識因素 (LSKF) (PIN、圖案或密碼)、安全密碼重置令牌或客戶端的情況下無法解鎖它們以及用於“重新啟動時恢復”操作的服務器端密鑰。僅允許為工作配置文件和完全託管的設備創建密碼重置令牌。
為了實現這一點, 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 密鑰派生的軟件密鑰,第二次使用非身份驗證綁定的密鑰庫密鑰。這提供了 SE 強制的 LSKF 猜測速率限制。
如果設備沒有 SE,則LockSettingsService
會使用延伸的 LSKF 作為Gatekeeper密碼。然後, LockSettingsService
對合成密碼進行兩次加密:第一次使用從延伸的LSKF 和可秒丟棄文件的哈希派生的軟件密鑰,第二次使用與Gatekeeper 註冊進行身份驗證綁定的密鑰庫密鑰。這提供了 LSKF 猜測的 TEE 強制速率限制。
當 LSKF 更改時, LockSettingsService
會刪除與合成密碼與舊 LSKF 的綁定相關的所有信息。在支持 Weaver 或防回滾密鑰庫密鑰的設備上,這可以保證舊綁定的安全刪除。因此,即使用戶沒有 LSKF,也會應用此處描述的保護。
Android 7.0 及更高版本支持基於文件的加密 (FBE)。基於文件的加密允許使用不同的密鑰對不同的文件進行加密,這些密鑰可以獨立解鎖。
本文介紹如何在新設備上啟用基於文件的加密,以及系統應用程序如何使用直接啟動 API 為用戶提供最佳、最安全的體驗。
所有搭載 Android 10 及更高版本的設備都需要使用基於文件的加密。
直接啟動
基於文件的加密啟用了 Android 7.0 中引入的一項稱為“直接啟動”的新功能。直接啟動允許加密設備直接啟動至鎖定屏幕。以前,在使用全盤加密(FDE) 的加密設備上,用戶需要提供憑據才能訪問任何數據,從而導致手機無法執行除最基本的操作之外的所有操作。例如,警報無法運行,無障礙服務無法使用,電話無法接聽電話,但僅限於基本的緊急撥號器操作。
隨著基於文件的加密 (FBE) 和新 API 的引入,使應用程序能夠感知加密,這些應用程序可以在有限的上下文中運行。這可能發生在用戶提供憑據之前,同時仍然保護私人用戶信息。
在啟用 FBE 的設備上,設備的每個用戶都有兩個可供應用程序使用的存儲位置:
- 憑證加密 (CE) 存儲,這是默認存儲位置,僅在用戶解鎖設備後才可用。
- 設備加密 (DE) 存儲,這是在直接啟動模式期間和用戶解鎖設備後都可用的存儲位置。
這種分離使工作配置文件更加安全,因為加密不再僅基於啟動時密碼,因此一次可以保護多個用戶。
直接啟動 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 加密。
- HAL 版本 1.0 或更高版本的Keymaster 支持。不支持 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=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
To further improve performance and reduce power usage, device manufacturers may also consider implementing inline encryption hardware , which encrypts/decrypts the data while it is on the way to/from the storage device. The Android common kernels (version 4.14 and higher) contain a framework that allows inline encryption to be used when hardware and vendor driver support is available. The inline encryption framework can be enabled by setting the following kernel configuration options:
CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_FS_ENCRYPTION=y CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
If your device uses UFS-based storage, also enable:
CONFIG_SCSI_UFS_CRYPTO=y
If your device uses eMMC-based storage, also enable:
CONFIG_MMC_CRYPTO=y
Enabling file-based encryption
Enabling FBE on a device requires enabling it on the internal storage ( userdata
). This also automatically enables FBE on adoptable storage; however, the encryption format on adoptable storage may be overridden if necessary.
Internal storage
FBE is enabled by adding the option fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]]
to the fs_mgr_flags column of the fstab
line for userdata
. This option defines the encryption format on internal storage. It contains up to three colon-separated parameters:
- The
contents_encryption_mode
parameter defines which cryptographic algorithm is used to encrypt file contents. It can be eitheraes-256-xts
oradiantum
. Since Android 11 it can also be left empty to specify the default algorithm, which isaes-256-xts
. - The
filenames_encryption_mode
parameter defines which cryptographic algorithm is used to encrypt file names. It can be eitheraes-256-cts
,aes-256-heh
,adiantum
, oraes-256-hctr2
. If not specified, it defaults toaes-256-cts
ifcontents_encryption_mode
isaes-256-xts
, or toadiantum
ifcontents_encryption_mode
isadiantum
. - The
flags
parameter, new in Android 11, is a list of flags separated by the+
character. The following flags are supported:- The
v1
flag selects version 1 encryption policies; thev2
flag selects version 2 encryption policies. Version 2 encryption policies use a more secure and flexible key derivation function . The default is v2 if the device launched on Android 11 or higher (as determined byro.product.first_api_level
), or v1 if the device launched on Android 10 or lower. - The
inlinecrypt_optimized
flag selects an encryption format that is optimized for inline encryption hardware that doesn't handle large numbers of keys efficiently. It does this by deriving just one file contents encryption key per CE or DE key, rather than one per file. The generation of IVs (initialization vectors) is adjusted accordingly. - The
emmc_optimized
flag is similar toinlinecrypt_optimized
, but it also selects an IV generation method that limits IVs to 32 bits. This flag should only be used on inline encryption hardware that is compliant with the JEDEC eMMC v5.2 specification and therefore supports only 32-bit IVs. On other inline encryption hardware, useinlinecrypt_optimized
instead. This flag should never be used on UFS-based storage; the UFS specification allows the use of 64-bit IVs. - On devices that support hardware-wrapped keys , the
wrappedkey_v0
flag enables the use of hardware-wrapped keys for FBE. This can only be used in combination with theinlinecrypt
mount option, and either theinlinecrypt_optimized
oremmc_optimized
flag.
- The
If you aren't using inline encryption hardware the recommended setting for most devices is fileencryption=aes-256-xts
. If you are using inline encryption hardware the recommended setting for most devices is fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized
(or equivalently fileencryption=::inlinecrypt_optimized
). On devices without any form of AES acceleration, Adiantum may be used instead of AES by setting fileencryption=adiantum
.
Since Android 14 (AOSP experimental), AES-HCTR2 is the preferred mode of filenames encryption for devices with accelerated cryptography instructions. However, only newer Android kernels support AES-HCTR2. In a future Android release, it is planned to become the default mode for filenames encryption. If your kernel has AES-HCTR2 support, it can be enabled for filenames encryption by setting filenames_encryption_mode
to aes-256-hctr2
. In the simplest case this would be done with fileencryption=aes-256-xts:aes-256-hctr2
.
On devices that launched with Android 10 or lower, fileencryption=ice
is also accepted to specify the use of the FSCRYPT_MODE_PRIVATE
file contents encryption mode. This mode is unimplemented by the Android common kernels, but it could be implemented by vendors using custom kernel patches. The on-disk format produced by this mode was vendor-specific. On devices launching with Android 11 or higher, this mode is no longer allowed and a standard encryption format must be used instead.
By default, file contents encryption is done using the Linux kernel's cryptography API. If you want to use inline encryption hardware instead, also add the inlinecrypt
mount option. For example, a full fstab
line might look like:
/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized
Adoptable storage
Since Android 9, FBE and adoptable storage can be used together.
Specifying the fileencryption
fstab option for userdata
also automatically enables both FBE and metadata encryption on adoptable storage. However, you may override the FBE and/or metadata encryption formats on adoptable storage by setting properties in PRODUCT_PROPERTY_OVERRIDES
.
On devices that launched with Android 11 or higher, use the following properties:
-
ro.crypto.volume.options
(new in Android 11) selects the FBE encryption format on adoptable storage. It has the same syntax as the argument to thefileencryption
fstab option, and it uses the same defaults. See the recommendations forfileencryption
above for what to use here. -
ro.crypto.volume.metadata.encryption
selects the metadata encryption format on adoptable storage. See the metadata encryption documentation .
On devices that launched with Android 10 or lower, use the following properties:
-
ro.crypto.volume.contents_mode
selects the contents encryption mode. This is equivalent to the first colon-separated field ofro.crypto.volume.options
. -
ro.crypto.volume.filenames_mode
selects the filenames encryption mode. This is equivalent to the second colon-separated field ofro.crypto.volume.options
, except that the default on devices that launched with Android 10 or lower isaes-256-heh
. On most devices, this needs to be explicitly overridden toaes-256-cts
. -
ro.crypto.fde_algorithm
andro.crypto.fde_sector_size
select the metadata encryption format on adoptable storage. See the metadata encryption documentation .
Integrating with Keymaster
The Keymaster HAL should be started as part of the early_hal
class. This is because FBE requires that Keymaster be ready to handle requests by the post-fs-data
boot phase, which is when vold
sets up the initial keys.
Excluding directories
init
applies the system DE key to all top-level directories of /data
, except for directories that must be unencrypted: the directory that contains the system DE key itself, and directories that contain user CE or DE directories. Encryption keys apply recursively and cannot be overridden by subdirectories.
In Android 11 and higher, the key that init
applies to directories can be controlled by the encryption=<action>
argument to the mkdir
command in init scripts. The possible values of <action>
are documented in the README for the Android init language .
In Android 10, the init
encryption actions were hardcoded into the following location:
/system/extras/libfscrypt/fscrypt_init_extensions.cpp
In Android 9 and earlier, the location was:
/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp
It is possible to add exceptions to prevent certain directories from being encrypted at all. If modifications of this sort are made then the device manufacturer should include SELinux policies that only grant access to the applications that need to use the unencrypted directory. This should exclude all untrusted applications.
The only known acceptable use case for this is in support of legacy OTA capabilities.
Supporting Direct Boot in system applications
Making applications Direct Boot aware
To facilitate rapid migration of system apps, there are two new attributes that can be set at the application level. The defaultToDeviceProtectedStorage
attribute is available only to system apps. The directBootAware
attribute is available to all.
<application android:directBootAware="true" android:defaultToDeviceProtectedStorage="true">
The directBootAware
attribute at the application level is shorthand for marking all components in the app as being encryption aware.
The defaultToDeviceProtectedStorage
attribute redirects the default app storage location to point at DE storage instead of pointing at CE storage. System apps using this flag must carefully audit all data stored in the default location, and change the paths of sensitive data to use CE storage. Device manufactures using this option should carefully inspect the data that they are storing to ensure that it contains no personal information.
When running in this mode, the following System APIs are available to explicitly manage a Context backed by CE storage when needed, which are equivalent to their Device Protected counterparts.
-
Context.createCredentialProtectedStorageContext()
-
Context.isCredentialProtectedStorage()
Supporting multiple users
Each user in a multi-user environment gets a separate encryption key. Every user gets two keys: a DE and a CE key. User 0 must log into the device first as it is a special user. This is pertinent for Device Administration uses.
Crypto-aware applications interact across users in this manner: INTERACT_ACROSS_USERS
and INTERACT_ACROSS_USERS_FULL
allow an application to act across all the users on the device. However, those apps will be able to access only CE-encrypted directories for users that are already unlocked.
An application may be able to interact freely across the DE areas, but one user unlocked does not mean that all the users on the device are unlocked. The application should check this status before trying to access these areas.
Each work profile user ID also gets two keys: DE and CE. When the work challenge is met, the profile user is unlocked and the Keymaster (in TEE) can provide the profile's TEE key.
Handling updates
The recovery partition is unable to access the DE-protected storage on the userdata partition. Devices implementing FBE are strongly recommended to support OTA using A/B system updates . As the OTA can be applied during normal operation there is no need for recovery to access data on the encrypted drive.
When using a legacy OTA solution, which requires recovery to access the OTA file on the userdata
partition:
- Create a top-level directory (for example
misc_ne
) in theuserdata
partition. - Configure this top-level directory to be unencrypted (see Excluding directories ).
- Create a directory within the top-level directory to hold OTA packages.
- Add an SELinux rule and file contexts to control access to this directory and it contents. Only the process or applications receiving OTA updates should be able to read and write to this directory. No other application or process should have access to this directory.
Validation
To ensure the implemented version of the feature works as intended, first run the many CTS encryption tests, such as DirectBootHostTest and EncryptionTest .
If the device is running Android 11 or higher, also run vts_kernel_encryption_test :
atest vts_kernel_encryption_test
or:
vts-tradefed run vts -m vts_kernel_encryption_test
In addition, device manufacturers may perform the following manual tests. On a device with FBE enabled:
- Check that
ro.crypto.state
exists- Ensure
ro.crypto.state
is encrypted
- Ensure
- Check that
ro.crypto.type
exists- Ensure
ro.crypto.type
is set tofile
- Ensure
Additionally, testers can boot a userdebug
instance with a lockscreen set on the primary user. Then adb
shell into the device and use su
to become root. Make sure /data/data
contains encrypted filenames; if it does not, something is wrong.
Device manufacturers are also encouraged to explore running the upstream Linux tests for fscrypt on their devices or kernels. These tests are part of the xfstests filesystem test suite. However, these upstream tests are not offically supported by Android.
AOSP implementation details
This section provides details on the AOSP implementation and describes how file-based encryption works. It should not be necessary for device manufacturers to make any changes here to use FBE and Direct Boot on their devices.
fscrypt encryption
The AOSP implementation uses "fscrypt" encryption (supported by ext4 and f2fs) in the kernel and normally is configured to:
- Encrypt file contents with AES-256 in XTS mode
- Encrypt file names with AES-256 in CBC-CTS mode
Adiantum encryption is also supported. When Adiantum encryption is enabled, both file contents and file names are encrypted with Adiantum.
fscrypt supports two versions of encryption policies: version 1 and version 2. Version 1 is deprecated, and the CDD requirements for devices launching with Android 11 and higher are only compatible with version 2. Version 2 encryption policies use HKDF-SHA512 to derive the actual encryption keys from the userspace-supplied keys.
For more information about fscrypt, see the upstream kernel documentation .
Storage classes
The following table lists the FBE keys and the directories they protect in more detail:
Storage class | Description | Directories |
---|---|---|
System DE | Device-encrypted data not tied to a particular user | /data/system , /data/app , and various other subdirectories of /data |
Per-boot | Ephemeral system files that don't need to survive a reboot | /data/per_boot |
User CE (internal) | Per-user credential-encrypted data on internal storage |
|
User DE (internal) | Per-user device-encrypted data on internal storage |
|
User CE (adoptable) | Per-user credential-encrypted data on adoptable storage |
|
User DE (adoptable) | Per-user device-encrypted data on adoptable storage |
|
Key storage and protection
All FBE keys are managed by vold
and are stored encrypted on-disk, except for the per-boot key which is not stored at all. The following table lists the locations in which the various FBE keys are stored:
Key type | Key location | Storage class of key location |
---|---|---|
System DE key | /data/unencrypted | Unencrypted |
User CE (internal) keys | /data/misc/vold/user_keys/ce/${user_id} | System DE |
User DE (internal) keys | /data/misc/vold/user_keys/de/${user_id} | System DE |
User CE (adoptable) keys | /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} | User CE (internal) |
User DE (adoptable) keys | /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} | User DE (internal) |
As shown in the preceding table, most FBE keys are stored in directories that are encrypted by another FBE key. Keys cannot be unlocked until the storage class that contains them has been unlocked.
vold
also applies a layer of encryption to all FBE keys. Every key besides CE keys for internal storage is encrypted with AES-256-GCM using its own Keystore key that is not exposed outside the TEE. This ensures that FBE keys cannot be unlocked unless a trusted operating system has booted, as enforced by Verified Boot . Rollback resistance is also requested on the Keystore key, which allows FBE keys to be securely deleted on devices where Keymaster supports rollback resistance. As a best-effort fallback for when rollback resistance is unavailable, the SHA-512 hash of 16384 random bytes stored in the secdiscardable
file stored alongside the key is used as the application ID tag of the Keystore key. All these bytes need to be recovered to recover an FBE key.
CE keys for internal storage receive a stronger level of protection that ensures they cannot be unlocked without knowing either the user's Lock Screen Knowledge Factor (LSKF) (PIN, pattern, or password), a secure passcode reset token , or both the client-side and server-side keys for a Resume-on-Reboot operation. Passcode reset tokens are only allowed to be created for work profiles and fully managed devices .
To achieve this, vold
encrypts each CE key for internal storage using an AES-256-GCM key derived from the user's synthetic password . The synthetic password is an immutable high-entropy cryptographic secret that is randomly generated for each user. LockSettingsService
in system_server
manages the synthetic password and the ways in which it is protected.
To protect the synthetic password with the LSKF, LockSettingsService
first stretches the LSKF by passing it through scrypt
, targeting a time of about 25 ms and a memory usage of about 2 MiB. Since LSKFs are usually short, this step usually does not provide much security. The main layer of security is the Secure Element (SE) or TEE-enforced ratelimiting described below.
If the device has a Secure Element (SE), then LockSettingsService
maps the stretched LSKF to a high-entropy random secret stored in the SE using the Weaver HAL . LockSettingsService
then encrypts the synthetic password twice: first with a software key derived from the stretched LSKF and the Weaver secret, and second with a non-auth-bound Keystore key. This provides SE-enforced ratelimiting of LSKF guesses.
If the device doesn't have a SE, then LockSettingsService
instead uses the stretched LSKF as a Gatekeeper password. LockSettingsService
then encrypts the synthetic password twice: first with a software key derived from the stretched LSKF and the hash of a secdiscardable file, and second with a Keystore key that is auth-bound to the Gatekeeper enrollment. This provides TEE-enforced ratelimiting of LSKF guesses.
When the LSKF is changed, LockSettingsService
deletes all information associated with the binding of the synthetic password to the old LSKF. On devices that support Weaver or rollback resistant Keystore keys, this guarantees secure deletion of the old binding. For this reason, the protections described here are applied even when the user does not have an LSKF.