硬體包裝的金鑰

如同大多數的磁碟與檔案加密軟體,Android 的儲存空間加密機制一樣 通常依賴系統記憶體中的原始加密金鑰 才能加密即使是透過專用硬體而非軟體執行加密作業,軟體通常仍需要管理原始加密金鑰。

這在傳統上並未被視為問題,因為在離線攻擊期間,系統不會顯示金鑰,而這正是儲存空間加密功能旨在防範的主要攻擊類型。不過,我們希望能提供更強大的防護,對抗其他類型的攻擊,例如冷啟動攻擊,以及線上攻擊,攻擊者可能會在未完全危害裝置的情況下,洩漏系統記憶體。

為解決這個問題,Android 11 導入了支援功能 「硬體包裝金鑰」,其中必須有硬體支援。 硬體包裝的金鑰是原始形式的儲存金鑰 專用硬體;軟體只能在已包裝的金鑰中查看和處理這些金鑰 (加密) 表單。這個硬體必須能夠產生及匯入 儲存空間金鑰、以暫時和長期形式包裝儲存金鑰, 子鍵,直接將一個子金鑰編寫為內嵌加密引擎,以及 傳回另一個子鍵到軟體。

注意:「內嵌加密引擎」(或「內嵌加密硬體」) 是指在資料傳輸至/從儲存裝置的過程中,用於加密/解密資料的硬體。通常是 UFS 或 eMMC 主機控制器,可實作對應 JEDEC 規格定義的加密擴充功能。

設計

本節會說明硬體包裝的金鑰功能設計,包括 所需的硬體支援本討論著重於檔案型加密 (FBE),但 解決方案適用於中繼資料 加密

如要避免需要使用系統記憶體中的原始加密金鑰, 這些金鑰只儲存在內嵌加密引擎的金鑰運算單元中。不過, 方法會產生一些問題

  • 加密金鑰的數量可能會超過金鑰運算單元數量。
  • 內嵌加密引擎只能用於加密/解密磁碟上的完整資料區塊。不過,在 FBE 的情況下,軟體仍需能夠執行其他加密編譯作業,例如檔案名稱加密和衍生金鑰 ID。軟體仍需要存取原始 FBE 金鑰,才能執行這項其他作業。

為避免這些問題,儲存金鑰會改為硬體包裝金鑰,只能由專用硬體解開並使用。因此可支援的金鑰數量沒有限制。此外,金鑰階層會經過修改,並部分移至此硬體,讓子金鑰可傳回至軟體,用於無法使用內嵌加密編譯引擎的作業。

金鑰階層

您可以使用 KDF (金鑰衍生函式) (例如 HKDF) 從其他金鑰衍生金鑰,進而產生金鑰階層

下圖描述 FBE 在 「不會」使用硬體包裝的金鑰:

FBE 金鑰階層 (標準)
圖 1:FBE 鍵值階層 (標準)

FBE 類別金鑰是 Android 傳送給 Linux 的原始加密金鑰 來解鎖一組特定加密目錄,例如 特定 Android 使用者的憑證加密儲存空間。(在核心中, 稱為 fscrypt 主金鑰)。核心會從這個鍵衍生出下列子鍵:

  • 金鑰 ID。這個值會用於加密,而不會用於加密。 用於識別特定檔案或目錄的金鑰 並受到妥善保護
  • 檔案內容加密金鑰
  • 檔案名稱加密金鑰

相反地,下圖描述 FBE 的 使用的是硬體包裝的金鑰:

FBE 金鑰階層 (含硬體包裝金鑰)
圖 2 FBE 金鑰階層 (含硬體包裝金鑰)

與先前的情況相比,金鑰階層已新增一個層級,且檔案內容加密金鑰已重新定位。根目錄 節點仍代表 Android 傳遞給 Linux 以解鎖一組 加密目錄不過,現在金鑰採用暫時包裝的格式 您必須先傳遞至專屬硬體,才能使用這項功能。這個硬體必須 實作兩個介面,以使用暫時包裝的金鑰:

  • 一個介面,用於擷取 inline_encryption_key,並直接將其編程至內嵌加密引擎的鍵槽。允許附加檔案 軟體,無法存取原始檔案或軟體 鍵。在 Android 通用核心中,此介面會對應至 blk_crypto_ll_ops::keyslot_program 作業,而儲存空間驅動程式必須實作此作業。
  • 一個介面,用於衍生並傳回 sw_secret (「軟體密鑰」-- 在某些地方也稱為「原始密鑰」),這是 Linux 用來衍生檔案內容加密以外所有內容的子金鑰。在 Android 通用核心中,此介面會對應至 blk_crypto_ll_ops::derive_sw_secret 作業,而儲存空間驅動程式必須實作此作業。

導出 inline_encryption_keysw_secret 原始儲存金鑰,硬體必須使用經過加密的高強度 KDF。這個 KDF 必須遵循密碼編譯最佳做法,安全強度必須至少為 256 位元,也就是足以支援日後使用的任何演算法。而且必須使用 不重複標籤、背景資訊和應用程式專屬資訊字串 衍生各類型的子鍵,藉此確保產生的子鍵 加密作業,也就是說,得知其中一份資料後不會發現 其他。不需要延展金鑰,因為原始儲存金鑰已經是 完全隨機的隨機金鑰

就技術層面而言,您可以使用任何符合安全性需求的 KDF。 不過,為了測試,您必須在測試程式碼中重新實作相同的 KDF。目前,我們已審查並實作一個 KDF,您可以在 vts_kernel_encryption_test 的原始碼中找到該 KDF。硬體建議使用這個 KDF,該 KDF 會使用 NIST SP 800-108「KDF in Counter Mode」,並以 AES-256-CMAC 做為 PRF。請注意,您必須能夠相容 演算法的部分必須相同,包括選擇的 KDF 結構定義 為每個子鍵建立和標籤

金鑰包裝

為達到硬體包裝金鑰的安全性目標,我們有兩種金鑰包裝 定義:

  • 暫時包裝:硬體會使用金鑰加密原始金鑰 這組 ID 在每次啟動時隨機產生,不會直接公開 硬體元件
  • 長期包裝:硬體會使用 專屬永久金鑰,並非直接內建於硬體中 暴露於硬體外

所有傳遞至 Linux 核心的金鑰,都是為了解鎖儲存空間而暫時包裝的。這確保如果攻擊者能夠擷取 系統記憶體的使用中金鑰,那麼該金鑰也無法使用 自動關閉、重新啟動裝置。

此外,Android 仍須能夠儲存加密版本 這些金鑰就能一開始就解鎖原始 就是基於這個目的不過,建議您不要讓原始金鑰出現在系統記憶體中,這樣一來,即使在啟動期間擷取,也無法將原始金鑰擷取到裝置外使用。所以這個概念 而不是「長期包裝」

為了支援管理用這兩種不同方式包裝的金鑰,硬體必須 實作以下介面:

  • 產生及匯入儲存空間金鑰的介面,以長期包裝形式傳回。這些介面可經由 KeyMint,而且與 TAG_STORAGE_KEY KeyMint 標記相對應。 vold 會使用「產生」功能,為 Android 產生新的儲存空間金鑰,而 vts_kernel_encryption_test 會使用「匯入」功能匯入測試金鑰。
  • 這個介面可將長期包裝的儲存空間金鑰轉換為暫時包裝的儲存空間金鑰。這會對應至 convertStorageKeyToEphemeral KeyMint 方法。voldvts_kernel_encryption_test 都會使用這個方法解鎖儲存空間。

金鑰包裝演算法是實作詳細資料,但應使用 強大的 AEAD,例如 AES-256-GCM 與隨機 IV。

需要變更軟體

Android 開放原始碼計畫已有支援硬體包裝金鑰的基本架構。這包括 vold 等使用者空間元件的支援,以及 blk-cryptofscryptdm-default-key 中的 Linux 核心支援。

不過,您需要進行一些針對導入作業的調整。

KeyMint 異動

必須修改裝置的 KeyMint 實作項目,以便支援 TAG_STORAGE_KEY 並實作 convertStorageKeyToEphemeral 方法。

在 Keymaster 中,系統使用的是 exportKey convertStorageKeyToEphemeral

Linux 核心變更

必須修改裝置內嵌加密引擎的 Linux 核心驅動程式 可支援硬體包裝的金鑰

針對 android14 以上版本的核心,請在 blk_crypto_profile::key_types_supported 中設定 BLK_CRYPTO_KEY_TYPE_HW_WRAPPED,讓 blk_crypto_ll_ops::keyslot_programblk_crypto_ll_ops::keyslot_evict 支援程式設計/淘汰硬體包裝的鍵,並實作 blk_crypto_ll_ops::derive_sw_secret

針對 android12android13 核心,請在 blk_keyslot_manager::features 中設定 BLK_CRYPTO_FEATURE_WRAPPED_KEYS,讓 blk_ksm_ll_ops::keyslot_programblk_ksm_ll_ops::keyslot_evict 支援程式設計/淘汰硬體包裝金鑰,並實作 blk_ksm_ll_ops::derive_raw_secret

針對 android11 核心,請在 keyslot_manager::features 中設定 BLK_CRYPTO_FEATURE_WRAPPED_KEYS,讓 keyslot_mgmt_ll_ops::keyslot_programkeyslot_mgmt_ll_ops::keyslot_evict 支援程式設計/淘汰硬體包裝的鍵,並實作 keyslot_mgmt_ll_ops::derive_raw_secret

測試

雖然使用硬體包裝金鑰進行加密的測試比使用標準金鑰更難,但仍可透過匯入測試金鑰,並重新實作硬體執行的金鑰衍生作業來進行測試。在這個 在 vts_kernel_encryption_test 中。如要執行這項測試 執行:

atest -v vts_kernel_encryption_test

請閱讀測試記錄,並確認硬體包裝金鑰測試案例 (例如 FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicyDmDefaultKeyTest.TestHwWrappedKey) 並未因未偵測到硬體包裝金鑰的支援而略過,因為在這種情況下,測試結果仍會是「通過」。

啟用按鍵

一旦裝置的硬體包裝金鑰支援功能正常運作,您就可以 對裝置的 fstab 檔案進行下列變更 Android 用來加密 FBE 和中繼資料:

  • FBE:將 wrappedkey_v0 標記新增至 fileencryption 參數。舉例來說,請使用 fileencryption=::inlinecrypt_optimized+wrappedkey_v0。詳情請參閱 FBE 說明文件
  • 中繼資料加密:將 wrappedkey_v0 標記新增至 metadata_encryption 參數。舉例來說,請使用 metadata_encryption=:wrappedkey_v0。詳情請參閱結構描述資料加密說明文件