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 起,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
使用Walver HAL將延伸的 LSKF 對應到儲存在 SE 中的高熵隨機秘密。然後, LockSettingsService
對合成密碼進行兩次加密:第一次使用從延伸的 LSKF 和 Weaver 金鑰派生的軟體金鑰,第二次使用非身份驗證綁定的金鑰庫金鑰。這提供了 SE 強制的 LSKF 猜測速率限制。
如果設備沒有 SE, LockSettingsService
會使用延伸的 LSKF 作為Gatekeeper密碼。然後, LockSettingsService
對合成密碼進行兩次加密:第一次使用從延伸的LSKF 和可秒丟棄檔案的雜湊派生的軟體金鑰,第二次使用與Gatekeeper 註冊進行身份驗證綁定的金鑰庫密鑰。這提供了 LSKF 猜測的 TEE 強制速率限制。
當 LSKF 變更時, LockSettingsService
會刪除與合成密碼與舊 LSKF 的綁定相關的所有資訊。在支援 Weaver 或防回滾金鑰庫金鑰的裝置上,這可以確保舊綁定的安全刪除。因此,即使使用者沒有 LSKF,也會套用此處所述的保護。