Android 7.0 以上版本支援檔案型加密 (FBE)。FBE 可讓不同檔案使用不同金鑰加密,且這些金鑰可獨立解鎖。這些金鑰可用於加密檔案內容和檔案名稱。 使用 FBE 時,其他資訊 (例如目錄版面配置、檔案大小、權限和建立/修改時間) 不會加密。這些其他資訊統稱為檔案系統中繼資料。
Android 9 支援中繼資料加密。透過中繼資料加密功能,開機時的單一金鑰會加密 FBE 未加密的任何內容。這項金鑰受到 KeyMint (舊稱 Keymaster) 保護,而 KeyMint 本身則受到驗證開機程序保護。
啟用 FBE 時,系統一律會對可攜式儲存空間啟用中繼資料加密功能。 您也可以在內部儲存空間啟用中繼資料加密功能。搭載 Android 11 以上版本推出的裝置,必須啟用內部儲存空間的中繼資料加密功能。
在內部儲存空間中實作
如要在新裝置的內部儲存空間設定中繼資料加密,請設定 metadata
檔案系統、變更 init 序列,並在裝置的 fstab 檔案中啟用中繼資料加密。
必要條件
只有在首次格式化資料分割區時,才能設定中繼資料加密。因此,這項功能僅適用於新裝置,不應透過 OTA 變更。
如要加密中繼資料,必須在核心中啟用 dm-default-key
模組。在 Android 11 以上版本中,Android 通用核心 4.14 以上版本支援 dm-default-key
。這個版本的 dm-default-key
使用名為 blk-crypto 的硬體和供應商獨立加密架構。
如要啟用 dm-default-key
,請使用:
CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_DM_DEFAULT_KEY=y
dm-default-key
會盡可能使用內嵌加密硬體 (在資料傳輸至/自儲存裝置時加密/解密資料的硬體)。如果沒有使用內嵌加密硬體,也必須啟用核心的加密 API 做為備援:
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
未使用內嵌加密硬體時,也應啟用任何可用的 CPU 型加速功能,如 FBE 文件中所述。
在 Android 10 以下版本中,Android 通用核心不支援 dm-default-key
。因此,供應商必須實作 dm-default-key
。
設定中繼資料檔案系統
由於在有中繼資料加密金鑰之前,無法讀取 userdata 分區中的任何內容,因此分區表必須預留一個稱為「中繼資料分區」的獨立分區,用於儲存保護這個金鑰的 KeyMint Blob。中繼資料分割區應為 16 MB。
fstab.hardware
必須包含中繼資料檔案系統的項目,該檔案系統位於該分割區,並在 /metadata
掛接,包括 formattable
標記,確保在啟動時格式化。f2fs 檔案系統不適用於較小的磁碟分割區,建議改用 ext4。例如:
/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable
如要確保 /metadata
掛接點存在,請在 BoardConfig-common.mk
中加入下列程式碼:
BOARD_USES_METADATA_PARTITION := true
初始化序列變更
使用中繼資料加密時,必須先執行 vold
,再掛接 /data
。為確保系統及早啟動,請在 init.hardware.rc
中加入下列詩節:
# We need vold early for metadata encryption on early-fs start vold
在 init 嘗試掛接 /data
之前,KeyMint 必須處於執行中且準備就緒的狀態。
init.hardware.rc
應已包含 mount_all
指令,該指令會在 on
late-fs
節中掛接 /data
本身。在這行程式碼之前,請新增指令來執行 wait_for_keymaster
服務:
on late-fs … # Wait for Keymaster exec_start wait_for_keymaster # Mount RW partitions which need run fsck mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
開啟中繼資料加密功能
最後,請將 keydirectory=/metadata/vold/metadata_encryption
新增至 userdata
的 fstab
項目 fs_mgr_flags 欄。舉例來說,完整的 fstab 行可能如下所示:
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,inlinecrypt latemount,wait,check,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,quota,formattable
根據預設,內部儲存空間的中繼資料加密演算法為 AES-256-XTS。如要覆寫此設定,請在 fs_mgr_flags 欄中設定 metadata_encryption
選項:
- 在缺少 AES 加速功能的裝置上,可以透過設定
metadata_encryption=adiantum
啟用 Adiantum 加密。 - 在支援硬體包裝金鑰的裝置上,您可以設定
metadata_encryption=aes-256-xts:wrappedkey_v0
(或同等的metadata_encryption=:wrappedkey_v0
,因為aes-256-xts
是預設演算法),將中繼資料加密金鑰設為硬體包裝金鑰。
由於 Android 11 中 dm-default-key
的核心介面已變更,您也必須確保已在 device.mk
中為 PRODUCT_SHIPPING_API_LEVEL
設定正確值。舉例來說,如果裝置搭載 Android 11 (API 級別 30) 推出,device.mk
應包含:
PRODUCT_SHIPPING_API_LEVEL := 30
您也可以設定下列系統屬性,強制使用新的 dm-default-key
API,無論運送 API 級別為何:
PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.dm_default_key.options_format.version=2
驗證
如要確認中繼資料加密功能已啟用且正常運作,請執行下列測試。此外,也請留意下文所述的常見問題。
測試
首先,請執行下列指令,確認內部儲存空間已啟用中繼資料加密:
adb root
adb shell dmctl table userdata
畫面上應該會顯示類似以下的輸出內容:
Targets in the device-mapper table for userdata: 0-4194304: default-key, aes-xts-plain64 - 0 252:2 0 3 allow_discards sector_size:4096 iv_large_sectors
如果您在裝置的 fstab
中設定 metadata_encryption
選項,覆寫預設加密設定,輸出內容會與上述內容略有不同。舉例來說,如果您啟用 Adiantum 加密,則第三個欄位會是 xchacha12,aes-adiantum-plain64
,而不是 aes-xts-plain64
。
接著,執行 vts_kernel_encryption_test,驗證中繼資料加密和 FBE 的正確性:
atest vts_kernel_encryption_test
或:
vts-tradefed run vts -m vts_kernel_encryption_test
常見問題
在呼叫 mount_all
期間 (這會掛接中繼資料加密的 /data
分區),init
會執行 vdc 工具。vdc 工具會透過 binder
連線至 vold
,設定中繼資料加密裝置並掛接分割區。在這次呼叫期間,系統會封鎖 init
,且嘗試讀取或設定 init
屬性都會遭到封鎖,直到 mount_all
完成為止。如果在此階段,vold
的工作直接或間接遭到封鎖,無法讀取或設定屬性,就會導致死結。請務必確保 vold
能完成讀取金鑰、與 KeyMint 互動,以及掛接資料目錄的工作,且不會進一步與 init
互動。
如果 mount_all
執行時 KeyMint 尚未完全啟動,系統會等到讀取 init
的特定屬性後,才會回應 vold
,導致發生上述死結。將 exec_start wait_for_keymaster
放在相關 mount_all
呼叫上方,可確保 KeyMint 事先完整執行,避免發生死結。
合併儲存空間設定
自 Android 9 起,只要啟用 FBE,系統一律會在可攜式儲存空間上啟用某種形式的中繼資料加密功能,即使未在內部儲存空間啟用中繼資料加密功能也一樣。
在 AOSP 中,可採用儲存空間上的中繼資料加密有兩種實作方式:一種是已淘汰的 dm-crypt
實作方式,另一種是較新的 dm-default-key
實作方式。為確保裝置選取正確的實作方式,請確認已在 device.mk
中為 PRODUCT_SHIPPING_API_LEVEL
設定正確值。舉例來說,如果裝置搭載 Android 11 (API 級別 30) 推出,device.mk
應包含:
PRODUCT_SHIPPING_API_LEVEL := 30
您也可以設定下列系統屬性,強制使用新的磁碟區中繼資料加密方法 (和新的預設 FBE 政策版本),無論出貨 API 層級為何:
PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.volume.metadata.method=dm-default-key \ ro.crypto.dm_default_key.options_format.version=2 \ ro.crypto.volume.options=::v2
目前方法
如果裝置搭載 Android 11 以上版本,可攜式儲存空間的加密中繼資料會使用 dm-default-key
核心模組,與內部儲存空間相同。如要瞭解要啟用哪些核心設定選項,請參閱上方的必要條件。請注意,適用於裝置內部儲存空間的內嵌加密硬體可能無法用於可攜式儲存空間,因此可能需要 CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
。
根據預設,dm-default-key
磁碟區中繼資料加密方法會使用 AES-256-XTS 加密演算法,以及 4096 位元組的加密區塊。只要設定 ro.crypto.volume.metadata.encryption
系統屬性,即可覆寫演算法。這個屬性的值與上述 metadata_encryption
fstab 選項的語法相同。舉例來說,在缺少 AES 加速功能的裝置上,可以設定 ro.crypto.volume.metadata.encryption=adiantum
來啟用 Adiantum 加密。
舊版方法
在搭載 Android 10 以下版本的裝置上,可攜式儲存空間的加密中繼資料會使用 dm-crypt
核心模組,而非 dm-default-key
:
CONFIG_DM_CRYPT=y
與 dm-default-key
方法不同,dm-crypt
方法會導致檔案內容加密兩次:一次使用 FBE 金鑰,一次使用中繼資料加密金鑰。這種雙重加密方式會降低效能,而且由於 Android 可確保 FBE 金鑰至少與中繼資料加密金鑰一樣難以破解,因此不需要雙重加密即可達成中繼資料加密的安全目標。供應商可以自訂核心,避免雙重加密,特別是實作 allow_encrypt_override
選項,當系統屬性 ro.crypto.allow_encrypt_override
設為 true
時,Android 會將該選項傳遞至 dm-crypt
。Android 通用核心不支援這些自訂項目。
根據預設,dm-crypt
磁碟區中繼資料加密方法會使用 AES-128-CBC 加密演算法,搭配 ESSIV 和 512 位元組的加密區塊。您可以設定下列系統屬性 (也用於 FDE) 來覆寫這項設定:
ro.crypto.fde_algorithm
選取中繼資料加密演算法。選項包括aes-128-cbc
和adiantum
。只有在裝置缺少 AES 加速功能時,才能使用 Adiantum。ro.crypto.fde_sector_size
會選取加密貨幣產業規模。 可選擇 512、1024、2048 和 4096。如要使用 Adiantum 加密,請使用 4096。