系統單晶片 (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 系統 Daemon,透過 Binder API 提供所有 KeyStore 功能的存取權。這個精靈負責儲存基礎 KeyMint (或 Keymaster) 實作建立的 keyblob,其中包含加密的密鑰資料,因此金鑰庫可以儲存這些資料,但無法使用或揭露。
- KeyMint HAL 服務
- 實作
IKeyMintDeviceHAL 的 AIDL 伺服器,可提供基礎 KeyMint TA 的存取權。 - KeyMint 信任的應用程式 (TA)
- 在安全環境中執行的軟體 (通常是 ARM SoC 上的 TrustZone),可提供所有安全加密編譯作業。這個應用程式可以存取原始金鑰資料,並在允許使用金鑰前,驗證金鑰的所有存取控管條件。
LockSettingsService- 負責使用者驗證的 Android 系統元件,包括密碼和指紋。這項功能不屬於 KeyStore,但與 KeyStore 支援的驗證繫結金鑰概念相關,因為只有在使用者完成驗證後,才能使用這類金鑰。
LockSettingsService會與 Gatekeeper TA 和 Fingerprint TA 互動,取得驗證權杖,並提供給金鑰儲存空間精靈,而 KeyMint TA 會使用這些權杖。 - Gatekeeper TA
- 在安全環境中執行的元件,負責驗證使用者密碼及產生驗證權杖,向 KeyMint TA 證明特定使用者在特定時間點完成驗證。
- 指紋 TA
- 在安全環境中執行的元件,負責驗證使用者指紋,並產生驗證權杖,向 KeyMint TA 證明特定使用者在特定時間點完成驗證。
建築
Android Keystore API 和底層的 KeyMint HAL 提供基本但足夠的加密編譯基本元素,可使用存取權控管的硬體支援金鑰實作通訊協定。
KeyMint HAL 是原始設備製造商提供的服務,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,也無法使用。
Keystore 也支援另外兩個金鑰描述元網域,這些網域用於其他系統元件,不適用於應用程式建立的金鑰:
BLOB網域表示金鑰描述元中沒有金鑰的 ID,而是金鑰描述元本身持有 keyblob,且用戶端會處理 keyblob 儲存空間。用戶端 (例如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 版提供。KeyStore 提供數位簽署和驗證作業,以及產生和匯入非對稱簽署金鑰配對。許多裝置已實作這項功能,但僅靠簽章 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。