KeyStore 提供更安全的空間,用於建立、儲存及使用加密編譯 管理金鑰如果有硬體支援的金鑰儲存空間 時,金鑰內容較能安全避免從裝置中擷取。 Keymaster 實施的限制較難以破壞。
但只有已知 KeyStore 金鑰位於 硬體支援儲存空間在 Keymaster 1 中,應用程式 遠端伺服器。KeyStore Daemon 載入可用的 Keymaster HAL,並相信 HAL 所說的內容 與硬體備份相對應
為解決這個問題,Keymaster 在 Android 7.0 (Keymaster 2) 和 ID 中推出金鑰認證 Android 8.0 (Keymaster 3) 的認證。
金鑰認證旨在提供 判斷非對稱金鑰組是否採用硬體支援,以及其屬性為何 ,以及使用時所套用的限制。
ID 認證可讓裝置提供硬體 ID 證明。 例如序號或 IMEI。
金鑰認證
為支援金鑰認證,Android 7.0 推出了一組標記、類型和 轉換為 HAL
標記
Tag::ATTESTATION_CHALLENGE
Tag::INCLUDE_UNIQUE_ID
Tag::RESET_SINCE_ID_ROTATION
類型
Keymaster 2 以下版本
typedef struct { keymaster_blob_t* entries; size_t entry_count; } keymaster_cert_chain_t;
AttestKey
方法
Keymaster 3
attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams) generates(ErrorCode error, vec<vec<uint8_t>> certChain);
Keymaster 2 以下版本
keymaster_error_t (*attest_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_attest, const keymaster_key_param_set_t* attest_params, keymaster_cert_chain_t* cert_chain);
dev
是 Keymaster 裝置結構。keyToAttest
是從 要建立認證的generateKey
。attestParams
是 認證。這包括「Tag::ATTESTATION_CHALLENGE
」和 和Tag::RESET_SINCE_ID_ROTATION
Tag::APPLICATION_ID
和Tag::APPLICATION_DATA
。 如果指定金鑰 blob,則需使用最後兩個版本解密。 測試過程中certChain
是輸出參數,此參數會傳回 憑證項目 0 即為認證憑證 透過keyToAttest
驗證金鑰,其中包含 認證擴充套件。
attestKey
方法被視為對
已認證金鑰,因為隨時都可以呼叫,不需要符合
授權限制。舉例來說,如果認證金鑰需要使用者
並使用有效驗證,系統可以在沒有使用者的情況下產生認證
驗證。
認證憑證
認證憑證是標準的 X.509 憑證,可選用 包含認證金鑰說明的認證擴充資料。 憑證是以通過認證的認證金鑰簽署。認證金鑰 可能會使用與認證金鑰不同的演算法。
認證憑證包含下表中的欄位,且 包含任何其他欄位。部分欄位會指定固定的欄位值。康乃狄克州 測試可驗證憑證內容是否完全符合定義。
憑證 SEQUENCE
欄位名稱 (請參閱 RFC 5280)。 | 值 |
---|---|
tbsCertificate | TBS 憑證序列 |
signatureAlgorithm | 用於簽署金鑰的演算法演算法識別碼: EC 金鑰的 ECDSA、適用於 RSA 金鑰的 RSA 金鑰。 |
signatureValue | BIT STRING,以 ASN.1 DER 編碼 tbsCertificate 計算的簽章。 |
TBS 憑證序列
欄位名稱 (請參閱 RFC 5280)。 | 值 |
---|---|
version |
INTEGER 2 (代表 v3 憑證) |
serialNumber |
INTEGER 1 (固定值:所有憑證的值相同) |
signature |
用於簽署金鑰的演算法演算法 ID,例如 EC 金鑰的 ECDSA 金鑰 RSA 適用的 RSA 金鑰。 |
issuer |
與批次認證金鑰的主體欄位相同。 |
validity |
兩個日期的 SEQUENCE,內含
Tag::ACTIVE_DATETIME 和
Tag::USAGE_EXPIRE_DATETIME。
這些值是以毫秒為單位自 1970 年 1 月 1 日以來計算。
請參閱 RFC 5280 中的正確資訊
憑證中的日期表示法。 如果 Tag::ACTIVE_DATETIME 不存在,請使用
Tag::CREATION_DATETIME 。如果
Tag::USAGE_EXPIRE_DATETIME 不存在,請使用到期時間
批次認證金鑰憑證的日期。 |
subject |
CN =「Android KeyStore Key」(固定值:在「所有」憑證上相同) |
subjectPublicKeyInfo |
含有認證公開金鑰的 SubjectPublicKeyInfo。 |
extensions/Key Usage |
DigitalSignature:在金鑰用途為 KeyPurpose::SIGN 時設定,或
KeyPurpose::VERIFY 。未設定所有其他位元。 |
extensions/CRL Distribution Points |
值待定 |
extensions/"attestation" |
OID 為 1.3.6.1.4.1.11129.2.1.17; 。與所有情況相同 X.509 憑證擴充資料,內容會以 OCTET_STRING 表示。 包含認證 SEQUENCE 的 DER 編碼。 |
認證擴充功能
attestation
擴充功能包含 Keymaster 的完整說明
與金鑰相關的授權,在直接對應的架構中
加入 Android 和 Keymaster HAL 的授權清單當中的每個標記
授權清單會以 ASN.1 SEQUENCE
表示
項目,明確
標上 keymaster 標記編號,但類型描述元 (四高)
遮罩。
舉例來說,在 Keymaster 3 中,Tag::PURPOSE
是在
types.hal 為 ENUM_REP | 1
。以認證擴充功能來說
移除 ENUM_REP
值,保留 1
標記。
(針對 Keymaster 2 以下版本,KM_TAG_PURPOSE
定義於
keymaster_defs.h)。
系統會以簡單明瞭的方式將值轉譯為 ASN.1 類型,如下表所示:
Keymaster 類型 | ASN.1 類型 |
---|---|
ENUM |
INTEGER |
ENUM_REP |
INTEGER 集 |
UINT |
INTEGER |
UINT_REP |
INTEGER 集 |
ULONG |
INTEGER |
ULONG_REP |
INTEGER 集 |
DATE |
INTEGER (自格林威治標準時間 1970 年 1 月 1 日 00:00:00 起的毫秒數) |
BOOL |
NULL (在 Keymaster 中,標記存在表示 true,不存在表示 false)。 相同的語意也適用於 ASN.1 編碼) |
BIGNUM |
目前未使用,因此未定義任何對應關係 |
BYTES |
10 月 30 日 |
結構定義
認證擴充內容的說明如下 ASN.1 結構定義。
KeyDescription ::= SEQUENCE { attestationVersion INTEGER, # KM2 value is 1. KM3 value is 2. KM4 value is 3. attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), StrongBox (2), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL. digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, rollbackResistance [303] EXPLICIT NULL OPTIONAL, # KM4 activeDateTime [400] EXPLICIT INTEGER OPTIONAL originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, trustedUserPresenceRequired [507] EXPLICIT NULL OPTIONAL, # KM4 trustedConfirmationRequired [508] EXPLICIT NULL OPTIONAL, # KM4 unlockedDeviceRequired [509] EXPLICIT NULL OPTIONAL, # KM4 allApplications [600] EXPLICIT NULL OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rollbackResistant [703] EXPLICIT NULL OPTIONAL, # KM2 and KM3 only. rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, attestationApplicationId [709] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdBrand [710] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdDevice [711] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdProduct [712] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdSerial [713] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdImei [714] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdMeid [715] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdManufacturer [716] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL, # KM3 vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL, # KM4 bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL, # KM4 } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, verifiedBootHash OCTET_STRING, # KM4 } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
KeyDescription 欄位
《keymasterVersion
》和《attestationChallenge
》
識別出
而非透過標記,因此編碼格式的標記只會指定
欄位類型。其餘欄位會依照
結構定義。
欄位名稱 | 類型 | 值 |
---|---|---|
attestationVersion |
INTEGER | 認證結構定義版本:1、2 或 3。 |
attestationSecurity |
SecurityLevel | 此認證的安全性等級。軟體可能會 硬體支援金鑰的認證。這類認證無法信任,但前提是 Android 系統遭到入侵, |
keymasterVersion |
INTEGER | Keymaster 裝置的版本:0、1、2、3 或 4。 |
keymasterSecurity |
SecurityLevel | Keymaster 實作的安全性等級。 |
attestationChallenge |
10 月 30 日 | Tag::ATTESTATION_CHALLENGE 的值,已指定至認證要求。 |
uniqueId |
10 月 30 日 | 選用的不重複 ID (如有鍵)
Tag::INCLUDE_UNIQUE_ID |
softwareEnforced |
AuthorizationList | 非必要,不是 TEE 強制執行的 Keymaster 授權 (如果有的話) 不限。 |
teeEnforced |
AuthorizationList | 非必要,是 TEE 強制執行的 Keymaster 授權 (如有)。 |
AuthorizationList 欄位
AuthorizationList
欄位均為選填,會確實識別
並將類型位元遮蓋起來。
使用明確標記,因此欄位也會包含一個標記,指出
與 ASN.1 類型相關,以便進行剖析。
如要進一步瞭解每個欄位的值,請參閱 Keymaster 3 的 types.hal
和
keymaster_defs.h
代表 Keymaster 2 以下版本。Keymaster 標記名稱
已透過省略 KM_TAG
的方式轉換為欄位名稱
來變更
長尾草,所以 Tag::KEY_SIZE
變成
keySize
。
RootOfTrust 欄位
系統會指定 RootOfTrust
欄位的位置。
欄位名稱 | 類型 | 值 |
---|---|---|
verifiedBootKey |
10 月 30 日 | 驗證系統映像檔的金鑰安全雜湊。SHA-256 建議 |
deviceLocked |
BOOLEAN | 如果系統啟動載入程式已鎖定,則為「true」,表示只有已簽署的映像檔可以 更新,且驗證開機程序檢查已完成。 |
verifiedBootState |
VerifiedBootState | 驗證開機程序的狀態。 |
verifiedBootHash |
10 月 30 日 | 由驗證開機程序保護的所有資料摘要。使用的裝置 Android 驗證開機程序的 Android 驗證開機程序,這個值 包含 VBMeta 結構的摘要,或驗證開機程序 中繼資料結構如要進一步瞭解如何計算這個值,請參閱 VBMeta 摘要 |
VerifiedBootState 值
verifiedBootState
的值的意義如下:
值 | 意義 |
---|---|
Verified |
表示從系統啟動載入程式到已驗證的完整信任鏈結
包括系統啟動載入程式、啟動分區和所有已驗證的分區
多個分區 在此狀態下, verifiedBootKey 值是該嵌入的
憑證,這代表 ROM 中無變更的憑證。這個狀態與 驗證開機流程說明文件。 |
SelfSigned |
表示啟動分區已使用嵌入式
,且簽章有效。系統啟動載入程式會顯示警告
再允許啟動程序繼續進行。
在這個狀態下, verifiedBootKey 值是自我簽署的雜湊
憑證此狀態與黃色啟動狀態,如 驗證開機流程說明文件。 |
Unverified |
表示裝置可自由修改。裝置完整性還剩
使用者需要透過頻外驗證。系統啟動載入程式會向使用者顯示警告
,然後再允許啟動程序繼續進行。 在這個狀態下, verifiedBootKey 值為空白。這個狀態與 驗證開機流程說明文件。 |
Failed |
表示裝置驗證失敗。沒有認證憑證
實際上卻包含這個值,因為在這個狀態下,系統啟動載入程式會停止運作。是
查看完整內容 這個狀態與 驗證開機流程說明文件。 |
SecurityLevel 值
securityLevel
的值的意義如下:
值 | 意義 |
---|---|
Software |
建立或管理相關元素 (認證或 鍵) 是在 Android 系統中實作,如果系統發生錯誤,可能會進行變更 遭到入侵的漏洞 |
TrustedEnvironment |
建立或管理相關元素 (認證或 鍵) 是在受信任的執行環境 (TEE) 中實作。可以是 如果 TEE 遭到入侵,但 TEE 極度抗遠端,則為修改內容 也能防範直接硬體攻擊 |
StrongBox |
建立或管理相關元素 (認證或 金鑰) 是在專屬的硬體安全性模組中實作。可以是 在硬體安全性模組遭到入侵時修改,但極佳 可抵禦遠端入侵,可強力抵禦直接入侵 硬體攻擊 |
專屬 ID
專屬 ID 是可用於識別裝置的 128 位元值, 效期有限這個值的計算方式如下:
HMAC_SHA256(T || C || R, HBK)
其中:
T
是「時間計數器值」,計算方式是將Tag::CREATION_DATETIME
的值乘以 2592000000,捨棄任何 。每 30 天T
次變化 (2592000000 = 30 * 24 * 60) * 60 * 1000)。C
是Tag::APPLICATION_ID
的值- 如果
Tag::RESET_SINCE_ID_ROTATION
是 1,則R
為 1 attest_params 參數傳送至 attest_key 呼叫的值,如果 標記不存在。 HBK
是「受信任的」已知的硬體專屬密鑰 執行環境而且絕不會透露。密鑰至少包含 個別裝置專屬的 128 位元熵 (機率性) 這是因為熵長度為 128 位元)。HBK 應該是 透過 HMAC 或 AES_CMAC 取得融合金鑰內容。
將 HMAC_SHA256 輸出內容截斷至 128 位元。
認證金鑰和 憑證
有兩個金鑰:一個 RSA 和一個 ECDSA,以及對應的憑證鏈結 安全佈建到裝置上
Android 12 推出了遠端金鑰佈建功能,Android 13 則需要裝置 實際執行這些工作遠端金鑰佈建功能為現場裝置提供 每個應用程式的 ECDSA P256 認證憑證。這些憑證 使用時間比原廠佈建憑證的短時間長。
多個 IMEI
Android 14 的 Android 金鑰認證記錄。 如要實作這項功能,原始設備製造商 (OEM) 可以新增第二個 IMEI 的 KeyMint 標記。 擁有多個行動網路無線電的裝置越來越普遍 原始設備製造商 (OEM) 現可支援使用兩個 IMEI 的裝置
如果原始設備製造商 (OEM) 的裝置有次要 IMEI,則須提供次要 IMEI 提供給 KeyMint 的實作,讓這些實作 請務必使用與第一個 IMEI 相同的方式認證
ID 認證
Android 8.0 包含選用的 ID 認證支援 Keymaster 3.ID 認證可讓裝置提供硬體證明 識別資訊,例如序號或 IMEI。雖然選擇性功能 強烈建議所有 Keymaster 3 的實作都支援這項功能 因為能證明裝置的身分,支援各種用途 因為遠端設定可以 可以確定這是與正確的裝置交談,而不是假冒的裝置 身分)。
ID 認證的運作方式是建立裝置硬體 ID 的副本 確保只有受信任的執行環境 (TEE) 能在裝置之前存取 離開工廠。使用者可以解鎖裝置的系統啟動載入程式, 系統軟體和 Android 架構回報的 ID。 無法以這種方式操控 TEE 持有的 ID 副本 確保裝置 ID 認證只會用於 藉此遏止假冒行為。
ID 認證的主要 API 介面建構在現有金鑰之上 透過 Keymaster 2 推出的認證機制。請求 Keymaster 持有金鑰的認證憑證,呼叫端可能會要求 需將裝置的硬體 ID 納入認證中 憑證的中繼資料如果金鑰保留在 TEE 中,憑證會 傳回至已知的信任根接收這類憑證的接收者 驗證憑證及其內容,包括硬體 識別碼) 均由 TEE 編寫。系統要求加入硬體時 只有認證憑證中的 ID,TEE 認證只會提供給 儲存在裝置儲存空間中的識別碼 (在廠區填入)。
儲存空間屬性
保存裝置 ID 的儲存空間必須具備以下屬性:
- 系統會將從裝置原始 ID 衍生的值複製到 儲存空間。
destroyAttestationIds()
方法可以永久刪除 這項 ID 衍生資料副本「永久刪除」是指 資料會完全移除,因此不會恢復原廠設定 清除裝置上的資料即可還原。尤其是 對使用者解鎖系統啟動載入程式並變更其 系統軟體並修改 Android 傳回的 ID 架構。- 退貨授權設施應能 而是為硬體 ID 衍生資料產生新的副本。如此一來 通過退貨授權的裝置可再次執行 ID 認證。 必須為退貨授權設施使用的機制受到保護,讓使用者無法 便可自行呼叫,因為這樣他們就能取得 或欺騙性 ID
- 在 TEE 中,除了 Keymaster 信任的應用程式之外,沒有任何程式碼能讀取 保存在儲存空間中的識別碼。
- 儲存空間會遭到破壞:如果儲存空間內容 TEE 會將修改內容視為 ,並拒絕所有 ID 認證嘗試。在這個 簽署儲存體, 。
- 儲存空間不會保存原始 ID,因為 ID 認證 回答問題時,呼叫端一律會提供 已通過認證。TEE 只需要驗證這些值是否與自身值相符 。儲存原始值的安全雜湊,而非儲存 值就會啟用這項驗證。
營造業
如要建立具有上述屬性的實作,請儲存 下方結構中的 ID 衍生值不要儲存 ID 值,但系統中的一般位置除外,裝置擁有者 可能會因為 Root 權限而修改:
S = D || HMAC(HBK, D)
其中:
D = HMAC(HBK, ID1) || HMAC(HBK, ID2) || ... || HMAC(HBK, IDn)
HMAC
是包含適當安全雜湊的 HMAC 結構 (建議使用 SHA-256)HBK
是硬體繫結金鑰,並未用於其他用途ID1...IDn
是原始 ID 值; 的關聯 必須仰賴實作, 不同裝置的 ID 數量都不一樣||
表示串連
由於 HMAC 輸出內容是固定大小,因此不會有標頭或其他結構 才能找到個別 ID 雜湊或 D 的 HMAC。此外, 來檢查提供的值來執行認證,實作需要 驗證 S 的方法,是從 S 擷取 D,計算 HMAC(HBK, D),然後與 的值,以確認沒有個別編號被修改或毀損。另外, 導入作業必須針對所有個別 ID 使用常數比較 元素和 S 驗證無論 提供的 ID 數量,以及測試各部分的正確比對情形
硬體 ID
ID 認證支援下列硬體 ID:
- 品牌名稱,由 Android 中的
Build.BRAND
傳回 - Android 中
Build.DEVICE
傳回的裝置名稱 - 產品名稱,由 Android 中
Build.PRODUCT
傳回的產品名稱 - 製造商名稱,由
Build.MANUFACTURER
在 Android 中傳回 - Android 中
Build.MODEL
傳回的模型名稱 - 序號
- 所有無線電的 IMEI
- 所有無線電的 MEID
為支援裝置 ID 認證,裝置會對這些 ID 進行認證。所有語言 搭載 Android 的裝置擁有前六項,這是執行這項動作所需的應用程式 運作。如果裝置有整合式行動網路無線電, 也必須支持無線電晶片的 IMEI 和/或 MEID 認證
如要要求 ID 認證,您必須執行金鑰認證,並在其中包含 要在要求中認證的裝置 ID。這些 ID 會標記為:
ATTESTATION_ID_BRAND
ATTESTATION_ID_DEVICE
ATTESTATION_ID_PRODUCT
ATTESTATION_ID_MANUFACTURER
ATTESTATION_ID_MODEL
ATTESTATION_ID_SERIAL
ATTESTATION_ID_IMEI
ATTESTATION_ID_MEID
認證的 ID 是 UTF-8 編碼的位元組字串。這個格式適用於 數字 ID用於認證的每個 ID 都會以 UTF-8 編碼字串。
如果裝置不支援 ID 認證 (或
先前已呼叫 destroyAttestationIds()
,因此裝置無法
可驗證 ID 或憑證等任何金鑰認證要求
這些標記不會因 ErrorCode::CANNOT_ATTEST_IDS
而失敗。
如果裝置支援 ID 認證,且上述一或多個標記
已納入金鑰認證要求中,TEE 就會驗證 ID
與每項代碼提供的硬體 ID 相符。如果
一或多個 ID 不相符,整個認證就會失敗,
ErrorCode::CANNOT_ATTEST_IDS
。對相同代碼而言有效
多次提供資訊這在測試 IMEI 時非常實用:
一部裝置可能有多個無線電和多個 IMEI 的無線電。認證要求為
如果為每個 ATTESTATION_ID_IMEI
提供的值相符,就表示有效
其中一個裝置的無線電這項原則也適用於所有其他代碼。
如果認證成功,系統會將認證 ID 新增至 認證擴充功能 (OID 1.3.6.1.4.1.11129.2.1.17), 請參閱上述結構定義來自 Keymaster 2 的變更 認證結構定義會以粗體顯示,其中包含註解。
Java API
本節僅提供相關資訊,Keymaster 實作者 或使用 Java API這項資訊可協助實作者瞭解 瞭解應用程式如何使用這項功能系統元件可能會使用 所以這部分的內容不可視為常態。