單晶片系統 (SoC) 中的受信任執行環境 (TEE) 可讓 Android 裝置為 Android OS、平台服務,甚至是第三方應用程式提供硬體支援的強大安全服務 (以標準 Java Cryptography Architecture 的 Android 專屬擴充功能形式提供,請參閱 KeyGenParameterSpec
)。
詞彙解釋
以下簡要說明 Keystore 元件及其關係。
AndroidKeyStore
- 應用程式用來存取 KeyStore 功能的 Android Framework API 和元件。這是標準 Java Cryptography Architecture API 的實作項目,但也會新增 Android 專用的擴充功能,並包含在應用程式本身的程序空間中執行的 Java 程式碼。
AndroidKeyStore
會將應用程式的 Keystore 行為要求轉送至 keystore 精靈,藉此滿足要求。 - 金鑰庫精靈
- Android 系統精靈,可透過 Binder API 存取所有 KeyStore 功能。這個精靈負責儲存基礎 KeyMint (或 Keymaster) 實作建立的金鑰 Blob,其中包含加密的密鑰資料,因此金鑰庫可以儲存這些資料,但無法使用或揭露。
- KeyMint HAL 服務
- 實作
IKeyMintDevice
HAL 的 AIDL 伺服器,可存取基礎 KeyMint TA。 - KeyMint 可信任應用程式 (TA)
- 在安全環境中執行的軟體 (通常是 ARM SoC 上的 TrustZone),可提供所有安全加密編譯作業。這個應用程式可以存取原始金鑰資料,並在允許使用金鑰前,驗證金鑰的所有存取權控制項條件。
LockSettingsService
- 負責使用者驗證的 Android 系統元件,包括密碼和指紋。這項功能不屬於 Keystore,但與 Keystore 相關,因為 Keystore 支援驗證繫結金鑰的概念:只有在使用者完成驗證後,才能使用金鑰。
LockSettingsService
會與 Gatekeeper TA 和指紋 TA 互動,取得驗證權杖,並提供給金鑰儲存空間精靈,而 KeyMint TA 會使用這些權杖。 - 總機人員 TA
- 在安全環境中執行的元件,負責驗證使用者密碼及產生驗證權杖,用來向 KeyMint TA 證明特定使用者在特定時間點完成驗證。
- 指紋 TA
- 在安全環境中執行的元件,負責驗證使用者指紋,並產生驗證權杖,用於向 KeyMint TA 證明特定使用者在特定時間點完成驗證。
建築
Android Keystore API 和底層的 KeyMint HAL 提供基本但足夠的加密基本元素,可使用存取權控管的硬體支援金鑰實作通訊協定。
KeyMint HAL 是 OEM 提供的服務,Keystore 服務會使用這項服務提供硬體支援的加密編譯服務。為確保私密金鑰內容安全無虞,HAL 實作不會在使用者空間,甚至核心空間中執行任何敏感作業。Android 中執行的 KeyMint HAL 服務會將敏感作業委派給在某種安全環境中執行的 TA,通常是透過以某種實作定義的線路格式封送及解封送要求。
產生的架構如下所示:

圖 1. 存取 KeyMint。
KeyMint HAL API 屬於低階 API,供平台內部元件使用,不會向應用程式開發人員公開。如要瞭解應用程式可用的高階 Java API,請前往 Android 開發人員網站。
存取權控管
Android Keystore 提供中央元件,可供應用程式和其他系統元件儲存及使用硬體支援的加密金鑰。因此,通常只有建立金鑰的應用程式或系統元件,才能存取個別金鑰。
KeyStore 網域
為支援這項存取權控管功能,系統會使用金鑰描述元向 Keystore 識別金鑰。這個金鑰描述元會指出描述元所屬的網域,以及該網域中的身分。
Android 應用程式會使用標準 Java Cryptography Architecture 存取 Keystore,並以字串別名識別金鑰。這種識別方法會在內部對應至 Keystore APP
網域,並納入呼叫端的 UID,以區分不同應用程式的金鑰,避免一個應用程式存取另一個應用程式的金鑰。
在內部,架構程式碼也會在載入金鑰後收到專屬的數字金鑰 ID。這個數字 ID 會做為 KEY_ID
網域中金鑰描述元的 ID。不過,存取權控管機制仍會運作:即使某個應用程式發現另一個應用程式的金鑰 ID,在正常情況下也無法使用。
不過,應用程式可能會將金鑰的使用權授予其他應用程式 (以 UID 識別)。這項授權作業會傳回專屬授權 ID,做為 GRANT
網域中金鑰描述元的 ID。同樣地,系統仍會執行存取權控管:即使第三方應用程式發現受讓人金鑰的授權 ID,也無法使用。
金鑰儲存區也支援另外兩個金鑰描述元網域,這些網域用於其他系統元件,不適用於應用程式建立的金鑰:
BLOB
網域表示金鑰描述元中沒有金鑰的 ID,而是保存金鑰 blob 本身,且用戶端會處理金鑰 blob 儲存空間。用戶端 (例如vold
) 需要在掛接資料分割區之前存取 Keystore,就會使用這項功能。SELINUX
網域可讓系統元件共用金鑰,存取權則由對應至 SELinux 標籤的數字 ID 管理 (請參閱 keystore_key 的 SELinux 政策)。
keystore_key 的 SELinux 政策
用於 Domain::SELINUX
金鑰描述元的 ID 值是在 keystore2_key_context
SELinux 政策檔案中設定。這些檔案中的每一行都會將數字對應至 SELinux 標籤,例如:
# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and # Settings to share Keystore keys. 102 u:object_r:wifi_key:s0
如果元件需要存取 SELINUX
網域中 ID 為 102 的金鑰,就必須有對應的 SELinux 政策。舉例來說,如要允許 wpa_supplicant
取得及使用這些鍵,請在 hal_wifi_supplicant.te
中新增下列程式碼:
allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };
Domain::SELINUX
鍵的數字 ID 會分成不同範圍,以支援不同分區,不會發生衝突:
分區 | 範圍 | 設定檔 |
---|---|---|
系統 | 0 ... 9,999 | /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
|
擴充系統 | 10,000 ... 19,999 | /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
|
產品 | 20,000 ... 29,999 | /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
|
供應商 | 30,000 ... 39,999 | /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts
|
系統分區已定義下列特定值:
名稱空間編號 | SEPolicy 標籤 | UID | 說明 |
---|---|---|---|
0 | su_key |
無 | 超級使用者金鑰。僅用於在 userdebug 和 eng 建構版本上進行測試。使用者建構版本不適用。 |
1 | shell_key |
無 | 可供 Shell 使用的命名空間。主要用於測試,但也可以從指令列用於使用者建構版本。 |
100 | vold_key |
無 | 供 vold 使用。 |
101 | odsign_key |
無 | 裝置端簽署 Daemon 使用。 |
102 | wifi_key |
AID_WIFI(1010) |
Android 的 Wi-Fi 子系統 (包括 wpa_supplicant ) 會使用這項設定。 |
103 | locksettings_key |
無 | LockSettingsService 使用 |
120 | resume_on_reboot_key |
AID_SYSTEM(1000) |
Android 系統伺服器會使用這項服務,在重新啟動後繼續執行作業。 |
存取向量
除了控管金鑰的整體存取權,金鑰儲存區還可控管金鑰可執行的作業。keystore2_key
權限說明位於 KeyPermission.aidl
檔案中。
系統權限
除了 keystore_key 的 SELinux 政策中說明的每個金鑰存取控制項之外,下表也列出執行各種系統和維護作業所需的其他 SELinux 權限:
權限 | 意義 |
---|---|
add_auth
|
將驗證權杖新增至 Keystore 時必須使用,由 Gatekeeper 或 BiometricManager 等驗證供應商使用。 |
clear_ns
|
刪除特定命名空間中的所有金鑰時必須使用,應用程式解除安裝時會做為維護作業。 |
list
|
系統會根據各種屬性 (例如擁有權或是否與驗證相關聯) 列舉金鑰,因此需要這項屬性。呼叫端列舉自己的命名空間時,不需要這項權限 (由 get_info 權限涵蓋)。 |
lock
|
用於通知金鑰儲存區裝置已鎖定,進而逐出超級金鑰,確保驗證繫結金鑰無法使用。 |
unlock
|
必須通知金鑰儲存區裝置已解鎖,並還原對超級金鑰的存取權,這些超級金鑰會保護與驗證相關聯的金鑰。 |
reset
|
將 Keystore 恢復原廠設定時,必須刪除所有對 Android OS 運作不重要的金鑰。 |
記錄
在 Android 5 以下版本中,Android 具有簡單的硬體支援加密服務 API,由 Keymaster 硬體抽象層 (HAL) 的 0.2 和 0.3 版提供。金鑰儲存區提供數位簽署和驗證作業,以及產生和匯入非對稱簽署金鑰配對。許多裝置已實作這項功能,但單靠簽章 API 無法輕易達成許多安全性目標。Android 6.0 擴充了 KeyStore API,提供更多功能。
Android 6.0
在 Android 6.0 中,Keymaster 1.0 新增了對稱加密基本元素、AES 和 HMAC,以及硬體支援金鑰的存取控制系統。存取權控管會在金鑰產生期間指定,並在金鑰的生命週期內強制執行。金鑰可設為只能在使用者通過驗證後使用,且只能用於特定用途或搭配特定加密編譯參數。
除了擴充密碼編譯基本功能的範圍,Android 6.0 中的 Keystore 還新增了下列項目:
- 使用控制機制,限制金鑰使用次數,降低金鑰遭濫用而導致安全漏洞的風險
- 存取權控管機制,可將金鑰限制為特定使用者、用戶端和定義的時間範圍
Android 7.0
在 Android 7.0 中,Keymaster 2 新增了金鑰認證和版本繫結支援。
金鑰認證 提供含有金鑰詳細說明和存取控制項的公開金鑰憑證,方便遠端驗證金鑰是否位於安全硬體中,以及金鑰的設定。
版本繫結 可將金鑰繫結至作業系統和修補程式等級版本。這可確保攻擊者即使發現舊版系統或 TEE 軟體有弱點,也無法將裝置還原至有安全漏洞的版本,並使用新版建立的金鑰。此外,如果裝置升級至較新版本或修補程式等級,當裝置使用特定版本和修補程式等級的金鑰時,金鑰會先升級,才能使用,且舊版金鑰會失效。裝置升級時,金鑰會隨著裝置向前移動,但如果將裝置還原為先前的版本,金鑰就會無法使用。
Android 8.0
在 Android 8.0 中,Keymaster 3 從舊式 C 結構 HAL 轉換為 C++ HAL 介面,該介面是根據新硬體介面定義語言 (HIDL) 中的定義產生。這項變更會導致許多引數類型發生變化,但類型和方法會與舊類型和 HAL 結構體方法一一對應。
除了修訂這個介面外,Android 8.0 也擴充了 Keymaster 2 的認證功能,支援ID 認證。ID 認證提供有限的選用機制,可強烈認證硬體 ID,例如裝置序號、產品名稱和手機 ID (IMEI 或 MEID)。為實作這項新增功能,Android 8.0 變更了 ASN.1 認證結構定義,新增了 ID 認證。Keymaster 實作項目必須找出安全的方式來擷取相關資料項目,並定義安全且永久停用這項功能的機制。
Android 9
Android 9 的更新內容包括:
- 更新至 Keymaster 4
- 支援內嵌安全元件
- 支援安全金鑰匯入
- 支援 3DES 加密
- 變更版本繫結,以便為
boot.img
和system.img
分別設定版本,允許獨立更新
Android 10
Android 10 推出了 Keymaster HAL 4.1 版,新增了下列功能:
- 支援僅在裝置解鎖時可使用的金鑰
- 支援只能在早期開機階段使用的金鑰
- 選用支援硬體包裝的儲存空間金鑰
- (選用) 在 StrongBox 中支援裝置專屬認證
Android 12
Android 12 推出了新的 KeyMint HAL,取代 Keymaster HAL,但提供類似功能。除了上述所有功能外,KeyMint HAL 也包含:
- 支援 ECDH 金鑰協議
- 支援使用者指定的認證金鑰
- 支援使用次數有限的金鑰
Android 12 也包含新版的金鑰儲存系統精靈,以 Rust 重新編寫,稱為 keystore2
Android 13
Android 13 新增了 KeyMint HAL 第 2 版,支援用於簽署和金鑰協議的 Curve25519。