KeyMint 函式

本頁面提供額外詳細資訊和指南,協助 KeyMint 硬體抽象層 (HAL) 的實作者。HAL 的主要說明文件是 AIDL 介面規格

API 濫用

呼叫端可以使用有效的 API 參數授權建立 KeyMint 金鑰,但這會導致產生的金鑰不安全或無法使用。在這種情況下,KeyMint 實作項目不必失敗或發出診斷資訊。使用過小的金鑰、指定不相關的輸入參數、重複使用 IV 或 nonce、產生無用途的金鑰 (因此無用) 等,實作項目不應對這些問題進行診斷。

應用程式、架構和 Android KeyStore 必須負責確保對 KeyMint 模組的呼叫是合理且實用的。

addRngEntropy 進入點

addRngEntropy 進入點會將呼叫端提供的資訊熵新增至 KeyMint 實作用來產生金鑰和 IV 的隨機數字的集區。

KeyMint 實作項目需要將提供的資訊熵安全地混入其資源池,而該資源池也必須包含硬體隨機數產生器內部產生的資訊熵。應處理混合問題,讓攻擊者在預測從熵值集區產生的位元時,不會因為完全控制 addRngEntropy 提供的位元或硬體產生的位元 (但不同時控制兩者) 而獲得明顯優勢。

主要特徵

建立 KeyMint 金鑰的每個機制 (generateKeyimportKeyimportWrappedKey) 都會傳回新建立的金鑰特性,並適當劃分為可強制執行各項特性的安全性層級。傳回的特性包括建立金鑰時指定的所有參數 (Tag::APPLICATION_IDTag::APPLICATION_DATA 除外)。如果這些標記包含在鍵參數中,系統會將其從傳回的特性中移除,因此無法透過檢查傳回的 keyblob 找出其值。不過,這些值會以加密編譯方式繫結至金鑰 blob,因此如果在使用金鑰時未提供正確的值,就會導致使用失敗。同樣地,Tag::ROOT_OF_TRUST 會以加密方式繫結至金鑰,但無法在建立或匯入金鑰時指定,也不會傳回。

除了提供的標記之外,KeyMint 實作也會新增 Tag::ORIGIN,指出金鑰的建立方式 (KeyOrigin::GENERATEDKeyOrigin::IMPORTEDKeyOrigin::SECURELY_IMPORTED)。

無法復原

Tag::ROLLBACK_RESISTANCE 代表復原保護機制,表示使用 deleteKeydeleteAllKeys 刪除金鑰後,安全硬體會確保金鑰永遠無法再使用。

KeyMint 實作會將產生或匯入的金鑰內容以金鑰 blob 的形式傳回給呼叫端,這是經過加密及驗證的格式。當 Keystore 刪除金鑰 blob 時,金鑰就會消失,但先前已成功擷取金鑰內容的攻擊者,可能會將金鑰還原到裝置。

如果安全硬體可確保刪除的金鑰無法日後還原,則金鑰就具有回溯防護功能。這通常是透過在無法遭到攻擊者操控的可信位置中,儲存額外的關鍵中繼資料來達成。在行動裝置上,用於這項操作的機制通常是重播保護記憶體區塊 (RPMB)。由於可建立的金鑰數量基本上沒有上限,且用於防禦回溯的受信任儲存空間可能有大小限制,因此當儲存空間已滿時,實作可能會拒絕建立防禦回溯的金鑰要求。

開始

begin() 進入點會開始使用指定金鑰的加密編譯作業,並根據指定參數 (視情況而定) 執行特定用途。它會傳回用於完成作業的新 IKeyMintOperation Binder 物件。此外,系統會傳回挑戰值,用於驗證作業中的驗證權杖。

KeyMint 實作項目支援至少 16 個並行作業。KeyStore 最多可使用 15 個,vold 會保留一個用於密碼加密。當 KeyStore 有 15 個進行中的作業 (已呼叫 begin(),但未呼叫 finishabort),且收到開始第 16 個作業的要求時,它會對最近使用次數最少的作業呼叫 abort(),將有效作業數量減少至 14,然後再呼叫 begin() 來啟動新要求的作業。

如果在金鑰產生或匯入期間指定了 Tag::APPLICATION_IDTag::APPLICATION_DATA,對 begin() 的呼叫必須包含這些代碼,並在該方法的 params 引數中使用原先指定的值。

處理錯誤

如果 IKeyMintOperation 上的某個方法傳回的錯誤代碼不是 ErrorCode::OK,系統會中止作業,並使作業 Binder 物件失效。日後使用該物件時,都會傳回 ErrorCode::INVALID_OPERATION_HANDLE

授權強制執行

主要在 begin() 中執行金鑰授權強制執行作業。唯一的例外狀況是,鍵有一個或多個 Tag::USER_SECURE_ID 值,但沒有 Tag::AUTH_TIMEOUT 值。

在這種情況下,每個作業都需要金鑰授權,而 update()finish() 方法會在 authToken 引數中接收授權權杖。為確保權杖有效,KeyMint 實作方式如下:

  • 驗證驗證權杖上的 HMAC 簽名。
  • 檢查權杖是否包含與金鑰相關聯的安全使用者 ID。
  • 檢查權杖的驗證類型是否與金鑰的 Tag::USER_AUTH_TYPE 相符。
  • 檢查符記是否在挑戰欄位中包含目前作業的挑戰值。

如果不符合這些條件,KeyMint 會傳回 ErrorCode::KEY_USER_NOT_AUTHENTICATED

呼叫端會在每次呼叫 update()finish() 時提供驗證權杖。實作項目只能驗證權杖一次。