金鑰和 ID 認證

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_IDTag::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_DATETIMETag::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.halkeymaster_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)。
  • CTag::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:

  1. 品牌名稱,由 Android 中的 Build.BRAND 傳回
  2. Android 中 Build.DEVICE 傳回的裝置名稱
  3. 產品名稱,由 Android 中 Build.PRODUCT 傳回的產品名稱
  4. 製造商名稱,由 Build.MANUFACTURER 在 Android 中傳回
  5. Android 中 Build.MODEL 傳回的模型名稱
  6. 序號
  7. 所有無線電的 IMEI
  8. 所有無線電的 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這項資訊可協助實作者瞭解 瞭解應用程式如何使用這項功能系統元件可能會使用 所以這部分的內容不可視為常態。