Gatekeeper

Gatekeeper 子系統會在受信任的執行環境 (TEE) 中執行裝置圖案/密碼驗證。Gatekeeper 會使用採用專屬硬體的密鑰註冊及驗證密碼。此外,Gatekeeper 會限制連續失敗的驗證嘗試,且必須根據指定的逾時時間和指定的連續失敗嘗試次數,拒絕服務要求。

使用者驗證密碼時,Gatekeeper 會發出驗證權杖,並使用每個啟動 HMAC 金鑰簽署,該金鑰僅適用於安全元件,且此權杖會傳送至採用專屬硬體的 Keystore。也就是說,Gatekeeper 驗證權杖會通知 KeyStore,應用程式可以使用驗證繫結金鑰 (例如應用程式建立的金鑰)。

建築

Gatekeeper 包含三個主要元件:

  • gatekeeperd (Gatekeeper daemon):Android 中的 C++ 繫結器服務,包含實作 IGateKeeperService AIDL 介面的平台獨立邏輯,以基礎供應商專屬的 IGatekeeper 實作為基礎。
  • Gatekeeper 硬體抽象層 (HAL) 服務:IGatekeeper AIDL 介面的供應商專屬實作。這項 HAL 服務會在 Android 中執行,但核心 Gatekeeper 功能必須在安全環境中執行,因此通常會與 Gatekeeper TA 通訊。
  • Gatekeeper 可信任應用程式 (TA):在 TEE 中執行的供應商專屬實作,可執行實際的密碼或圖案驗證。

LockSettingsService 會透過 Binder 發出要求,並傳送至 Android 作業系統中的 gatekeeperd Daemon。gatekeeperd Daemon 接著會向 IGatekeeper HAL 服務提出要求,然後再傳送至 TEE 中對應的 Gatekeeper TA:

守門人流程

圖 1. GateKeeper 驗證的高階資料流。

gatekeeperd 守護程序可讓 Android 架構 API 存取 HAL,並參與向 Keystore 回報裝置驗證。gatekeeperd 守護程序會在自己的程序中執行,與系統伺服器分開。

HAL 實作

gatekeeperd 守護程序會使用 IGatekeeper HAL 與基礎 Gatekeeper TA 互動,進行密碼驗證。Gatekeeper TA 實作必須能夠簽署 (註冊) 及驗證 Blob。所有實作項目都應遵循標準格式,在每次密碼驗證成功時產生驗證權杖 (HardwareAuthToken)。如要進一步瞭解 HardwareAuthToken 的內容和語意,請參閱 HardwareAuthToken.aidl 定義。

IGatekeeper HAL 的供應商實作項目必須實作 enroll 和 verify 函式:

  • enroll 方法會擷取密碼 blob 並簽署,然後以控制代碼的形式傳回簽章。傳回的 blob (來自對 enroll 的呼叫) 必須具有 system/gatekeeper/include/gatekeeper/password_handle.h 所示的結構。
  • verify 函式必須比較所提供密碼產生的簽章,並確保與註冊的密碼控制代碼相符。

用於註冊和驗證的金鑰不得變更,且每次裝置啟動時都應重新衍生。

Trusty 和其他實作

Trusty 作業系統是 Google 針對 TEE 環境推出的開放原始碼受信任 OS,內含經核准的 Gatekeeper 實作。不過,只要 TEE 能夠存取永久硬體支援金鑰,以及在暫停時仍會計時的安全單調時鐘,任何 TEE OS 都可以實作 Gatekeeper。

Trusty 使用內部 IPC 系統,直接在 KeyMint (先前稱為 Keymaster) 和 Gatekeeper 的 Trusty 實作 (Trusty Gatekeeper) 之間傳遞共用密鑰。這個共用密鑰用於簽署傳送至 Keystore 的驗證權杖,以提供密碼驗證認證。Trusty Gatekeeper 每次使用時都會向 KeyMint 要求金鑰,且不會保留或快取該值。實作時,可以透過任何不影響安全性的方式分享這項密鑰。

用於註冊及驗證密碼的 HMAC 金鑰,只會衍生並保存在 Gatekeeper 中。

Android 提供通用的 C++ Gatekeeper 實作,只需新增裝置專屬常式即可完成;Trusty 實作即以此為基礎。如要使用 TEE 的裝置專屬程式碼實作 TEE Gatekeeper,請參閱 system/gatekeeper/include/gatekeeper/gatekeeper.h 中的函式和註解。符合規範的實作方式主要負責:

  • 遵守 IGatekeeper HAL。
  • 傳回的驗證權杖必須依據 HardwareAuthToken 規格 (如 HardwareAuthToken.aidl 所述) 格式化。
  • TEE Gatekeeper 必須能透過下列其中一種方式,與 KeyMint 共用 HMAC 金鑰:
    • 共用密鑰協議:Gatekeeper 可透過實作 ISharedSecret HAL,參與每次啟動時的 HMAC 金鑰協商。這需要 Gatekeeper 和 KeyMint 都能存取共同的預先共用密鑰。
    • 直接存取:Gatekeeper 可使用 TEE 內部處理序間通訊機制,視需要或在首次使用時 (之後會快取) 從 KeyMint 擷取 HMAC 金鑰。

使用者安全 ID (SID)

使用者 SID 是使用者的 TEE 表示法 (與 Android 使用者 ID 沒有強烈關聯)。每當使用者註冊新密碼,但未提供舊密碼時,系統就會使用加密編譯虛擬亂數產生器 (PRNG) 產生 SID。這稱為「不受信任」重新註冊,通常只會在使用者首次設定密碼或圖案時發生。

當使用者提供有效的舊密碼 (例如變更密碼時),系統會進行「信任」重新註冊。在這種情況下,使用者 SID 會遷移至新的密碼控制代碼,並保留與其繫結的金鑰。

註冊密碼時,使用者 SID 會與密碼控制代碼中的密碼一起納入 HMAC 驗證。

使用者 SID 包含在 verify() 函式傳回的 HardwareAuthToken 中,並與所有繫結驗證的 KeyStore 金鑰相關聯 (如要進一步瞭解 HardwareAuthToken 格式和 KeyStore,請參閱「驗證」)。

請注意,由於對 enroll() 函式的不信任呼叫會變更使用者 SID,因此呼叫會導致繫結至該密碼的金鑰失效。如果攻擊者控制 Android 作業系統,可以變更裝置密碼,但會在這個過程中破壞受根層級保護的機密金鑰。

要求節流

Gatekeeper 必須能夠安全地限制對使用者憑證進行暴力破解。如 GatekeeperVerifyResponse.aidl 所示,HAL 會傳回逾時時間 (以毫秒為單位)。逾時會通知用戶端,在逾時時間過後才能再次呼叫 Gatekeeper。如有待處理的逾時作業,Gatekeeper 不應處理要求。

Gatekeeper 必須先寫入失敗計數器,才能驗證使用者密碼。如果密碼驗證成功,失敗計數器應會清除。這可防止攻擊者在發出 verify 呼叫後停用內嵌 MMC (eMMC),藉此規避節流機制。enroll 函式也會驗證使用者密碼 (如有提供),且必須以相同方式進行節流。

如果裝置支援,強烈建議將失敗計數器寫入安全儲存空間。如果裝置不支援檔案型加密,或安全儲存空間速度太慢,實作項目可能會直接使用重播保護記憶體區塊 (RPMB)。