功能

本頁包含有關 Android 6.0 及更高版本中Keystore的加密功能的資訊。

密碼原語

Keystore 提供以下幾類操作:

  • 金鑰生成
  • 非對稱金鑰的匯入和匯出(無金鑰包裝)
  • 導入原始對稱金鑰(無金鑰包裝)
  • 使用適當的填充模式進行非對稱加密和解密
  • 使用消化和適當的填充模式進行非對稱簽名和驗證
  • 以適當的模式(包括 AEAD 模式)進行對稱加密和解密
  • 對稱訊息認證碼的產生和驗證

協定元素(例如目的、模式和填充)以及存取控制約束在產生或匯入金鑰時指定,並永久綁定到金鑰,確保金鑰不能以任何其他方式使用。

除了上面的列表之外,Keymaster 實作還提供了一項服務,但未作為 API 公開:隨機數產生。這在內部用於產生金鑰、初始化向量 (IV)、隨機填充和需要隨機性的安全協定的其他元素。

必要的原語

所有 Keymaster 實作都提供:

  • RSA
    • 2048、3072 和 4096 位元密鑰支持
    • 支持公共指數 F4 (2^16+1)
    • RSA 簽章的填充模式:
      • RSASSA-PSS ( PaddingMode::RSA_PSS )
      • RSASSA-PKCS1-v1_5 ( PaddingMode::RSA_PKCS1_1_5_SIGN )
    • RSA 簽章的摘要模式:
      • SHA-256
    • RSA加密/解密的填滿模式:
      • 無襯墊
      • RSAES-OAEP ( PaddingMode::RSA_OAEP )
      • RSAES-PKCS1-v1_5 ( PaddingMode::RSA_PKCS1_1_5_ENCRYPT )
  • 電子CDSA
    • 支援 224、256、384 和 521 位元金鑰支持,分別使用 NIST P-224、P-256、P-384 和 P-521 曲線
    • ECDSA 的摘要模式:
      • 無摘要(已棄用,將來將被刪除)
      • SHA-256
  • AES
    • 支援 128 和 256 位元密鑰
    • CBC 、CTR、ECB 和 GCM。 GCM 實作不允許使用小於 96 位元的標籤或非 96 位元的隨機數長度。
    • CBC 和 ECB 模式支援填充模式PaddingMode::NONEPaddingMode::PKCS7 。在沒有填充的情況下,如果輸入不是區塊大小的倍數,CBC 或 ECB 模式加密就會失敗。
  • HMAC SHA-256 ,任何金鑰大小至少為 32 位元組。

強烈建議在 Keymaster 實施中使用 SHA1 和 SHA2 系列的其他成員(SHA-224、SHA384 和 SHA512)。如果硬體 Keymaster 實作不提供它們,Keystore 將在軟體中提供它們。

也建議使用一些原語來實現與其他系統的互通性:

  • RSA 的金鑰尺寸較小
  • RSA 的任意公共指數

按鍵存取控制

如果攻擊者可以隨意使用基於硬體的密鑰,則永遠無法從設備中提取它們,因此無法提供太多的安全性(儘管它們比可以洩露的密鑰更安全)。因此,金鑰庫強制執行存取控制至關重要。

存取控制被定義為標籤/值對的「授權清單」。授權標籤是32位元整數,數值有多種類型。某些標籤可以重複以指定多個值。標籤是否可以重複在標籤的文件中指定。建立密鑰時,呼叫者指定一個授權清單。 Keystore 底層的 Keymaster 實作修改該列表以指定一些附加信息,例如密鑰是否具有回滾保護,並返回“最終”授權列表,編碼到返回的密鑰 blob 中。如果最終授權清單已修改,則任何使用金鑰進行任何加密操作的嘗試都會失敗。

對於 Keymaster 2 及更早版本,可能的標籤集在枚舉keymaster_authorization_tag_t中定義,並且是永久固定的(儘管可以擴展)。名稱以KM_TAG為前綴。標籤ID的前四位用於指示類型。

Keymaster 3 將KM_TAG前綴更改為Tag::

可能的類型包括:

ENUM許多標籤的值在枚舉中定義。例如, TAG::PURPOSE的可能值在枚舉keymaster_purpose_t中定義。

ENUM_REPENUM相同,只是標籤可以在授權清單中重複。重複表示多個授權值。例如,加密金鑰可能具有KeyPurpose::ENCRYPTKeyPurpose::DECRYPT

UINT 32 位元無符號整數。範例: TAG::KEY_SIZE

UINT_REPUINT相同,但標籤可以在授權清單中重複。重複表示多個授權值。

ULONG 64 位元無符號整數。範例: TAG::RSA_PUBLIC_EXPONENT

ULONG_REPULONG相同,但標籤可以在授權清單中重複。重複表示多個授權值。

DATE日期/時間值,以 1970 年 1 月 1 日以來的毫秒數表示。範例: TAG::PRIVKEY_EXPIRE_DATETIME

BOOL真或假。如果BOOL類型的標籤不存在,則假定為「假」;如果存在,則假定為「真」。範例: TAG::ROLLBACK_RESISTANT

BIGNUM任意長度的整數,以大端順序表示為位元組數組。範例: TAG::RSA_PUBLIC_EXPONENT

BYTES位元組序列。範例: TAG::ROOT_OF_TRUST

硬體與軟體實施

並非所有安全硬體實作都包含相同的功能。為了支援各種方法,Keymaster 區分了安全和非安全的世界存取控制實施,或分別是硬體和軟體實施。

所有實作:

  • 強制執行所有授權的精確匹配(而不是強制執行)。密鑰 blob 中的授權清單與密鑰產生期間傳回的授權完全匹配,包括排序。任何不匹配都會導致錯誤診斷。
  • 聲明其語意值被強制執行的授權。

用於宣告硬體強制授權的 API 機制位於keymaster_key_characteristics_t結構中。它將授權清單分為兩個子清單: hw_enforcedsw_enforced 。安全硬體負責根據其可執行的內容在每個值中放置適當的值。

此外,Keystore 還對所有授權實施基於軟體的強制執行,無論它們是否由安全硬體強制執行。

例如,考慮不支援金鑰過期的基於 TrustZone 的實作。仍然可以建立具有到期日的密鑰。此金鑰的授權清單將包含標籤TAG::ORIGINATION_EXPIRE_DATETIME和到期日。向 Keystore 請求金鑰特徵將在sw_enforced清單中找到此標記,且安全硬體不會強制執行過期要求。但是,嘗試使用過期後的金鑰將被 Keystore 拒絕。

如果隨後使用支援過期的安全硬體升級設備,則對密鑰特徵的請求將在hw_enforced列表中找到TAG::ORIGINATION_EXPIRE_DATETIME ,並且即使密鑰庫以某種方式被破壞或繞過,在過期後嘗試使用密鑰也會失敗。

有關確定密鑰是否由硬體支援的更多信息,請參閱密鑰證明

密碼訊息構造授權

以下標籤用於定義使用關聯金鑰的操作的加密特徵: TAG::ALGORITHMTAG::KEY_SIZETAG::BLOCK_MODETAG::PADDINGTAG::CALLER_NONCETAG::DIGEST

TAG::PADDINGTAG::DIGESTPaddingMode::BLOCK_MODE是可重複的,這表示多個值可以與單一鍵關聯,並且要使用的值在操作時指定。

目的

金鑰具有一組關聯的用途,表示為帶有標籤TAG::PURPOSE的一個或多個授權條目,該標籤定義瞭如何使用它們。目的是:

  • KeyPurpose::ENCRYPT
  • KeyPurpose::DECRYPT
  • KeyPurpose::SIGN
  • KeyPurpose::VERIFY

任何密鑰都可以具有這些用途的任何子集。請注意,某些組合會產生安全性問題。例如,可用於加密和簽署的 RSA 金鑰可讓攻擊者說服系統解密任意資料以產生簽章。

進出口

Keymaster 僅支援以 X.509 格式匯出公鑰以及匯入:

  • DER 編碼的 PKCS#8 格式的公鑰和私鑰對,沒有基於密碼的加密
  • 作為原始位元組的對稱金鑰

為了確保匯入的金鑰可以與安全產生的金鑰區分開來, TAG::ORIGIN包含在適當的金鑰授權清單中。例如,如果金鑰是在安全硬體中產生的,則會在金鑰特徵的hw_enforced清單中找到值為KeyOrigin::GENERATEDTAG::ORIGIN ,而匯入到安全硬體中的金鑰將具有值KeyOrigin::IMPORTED

使用者認證

安全 Keymaster 實作不實作使用者身份驗證,但依賴其他執行此操作的受信任應用程式。有關這些應用程式實現的接口,請參閱Gatekeeper 頁面

使用者身份驗證要求透過兩組標籤指定。第一組指示哪個使用者可以使用該金鑰:

  • TAG::ALL_USERS表示該密鑰可供所有使用者使用。如果存在,則TAG::USER_IDTAG::USER_SECURE_ID不存在。
  • TAG::USER_ID具有指定授權使用者 ID 的數值。請注意,這是 Android 用戶 ID(適用於多用戶),而不是應用程式 UID,並且僅由非安全軟體強制執行。如果存在,則TAG::ALL_USERS不存在。
  • TAG::USER_SECURE_ID具有一個 64 位數值,指定在安全性驗證令牌中提供的安全使用者 ID,以解鎖金鑰的使用。如果重複,並且在安全認證令牌中提供了任何值,則可以使用該金鑰。

第二組指示使用者是否以及何時需要進行身份驗證。如果這兩個標籤都不存在,但TAG::USER_SECURE_ID存在,則每次使用該金鑰都需要進行驗證。

  • NO_AUTHENTICATION_REQUIRED表示不需要使用者驗證,但金鑰仍只能由以TAG::USER_ID指定的使用者身分執行的應用程式使用。
  • TAG::AUTH_TIMEOUT是一個數值,以秒為單位指定使用者驗證需要多長時間才能授權金鑰使用。這僅適用於私鑰/秘密金鑰操作。公鑰操作不需要身份驗證。超時不會交叉重啟;重新啟動後,所有密鑰都「從未經過驗證」。逾時可以設定為一個較大的值,以指示每次啟動都需要進行一次身份驗證(2^32 秒約為 136 年;大概 Android 裝置重新啟動的頻率比該值更高)。

客戶端綁定

客戶端綁定(金鑰與特定客戶端應用程式的關聯)是透過可選的客戶端 ID 和一些可選的客戶端資料(分別為TAG::APPLICATION_IDTAG::APPLICATION_DATA )完成。金鑰庫將這些值視為不透明的 blob,僅確保每次使用時都呈現金鑰產生/導入期間呈現的相同 blob,並且逐字節相同。 Keymaster 不會傳回客戶端綁定資料。呼叫者必須知道它才能使用密鑰。

此功能不會向應用程式公開。

到期日

密鑰庫支援按日期限制密鑰使用。密鑰有效性開始和密鑰過期可以與密鑰關聯,如果當前日期/時間超出有效範圍,Keymaster 將拒絕執行密鑰操作。鍵的有效範圍由標籤TAG::ACTIVE_DATETIMETAG::ORIGINATION_EXPIRE_DATETIMETAG::USAGE_EXPIRE_DATETIME指定。 「起源」和「使用」之間的區別是基於金鑰是用於「起源」新的密文/簽名/等,還是「使用」現有的密文/簽名/等。請注意,這種區別不會暴露給應用程式。

TAG::ACTIVE_DATETIMETAG::ORIGINATION_EXPIRE_DATETIMETAG::USAGE_EXPIRE_DATETIME標記是可選的。如果標籤不存在,則假定相關金鑰始終可用於解密/驗證訊息。

由於掛鐘時間是由非安全世界提供的,因此與過期相關的標籤不太可能出現在硬體強制清單中。硬體強制執行過期要求安全世界以某種方式獲取可信任時間和數據,例如透過具有可信任遠端時間伺服器的質詢回應協定。

信任根綁定

金鑰庫要求將金鑰綁定到信任根,信任根是在啟動期間(最好由引導程式)提供給 Keymaster 安全硬體的位元串。此位元串以加密方式綁定到 Keymaster 管理的每個金鑰。

信任根由用於驗證啟動映像上的簽章和裝置的鎖定狀態的公鑰組成。如果更改公鑰以允許使用不同的系統映像,或更改鎖定狀態,則先前系統建立的受 Keymaster 保護的密鑰均不可用,除非恢復先前的信任根並且系統由該密鑰簽署的檔案將被啟動。目標是透過使攻擊者安裝的作業系統無法使用 Keymaster 金鑰來增加軟體強制金鑰存取控制的價值。

獨立按鍵

某些 Keymaster 安全硬體可能選擇在內部儲存密鑰材料並傳回句柄而不是加密的密鑰材料。或者可能存在其他情況,其中在某些其他非安全或安全世界系統組件可用之前無法使用金鑰。 Keymaster HAL 允許呼叫者透過TAG::STANDALONE標籤請求「獨立」金鑰,這意味著除了 blob 和正在運行的 Keymaster 系統之外不需要任何資源。可以檢查與密鑰相關聯的標籤以查看密鑰是否是獨立的。目前僅定義了兩個值:

  • KeyBlobUsageRequirements::STANDALONE
  • KeyBlobUsageRequirements::REQUIRES_FILE_SYSTEM

此功能不會向應用程式公開。

速度

建立時,可以使用TAG::MIN_SECONDS_BETWEEN_OPS指定最大使用速度。如果操作執行時間早於TAG::MIN_SECONDS_BETWEEN_OPS秒,TrustZone 實作將拒絕使用該金鑰執行加密操作。

實現速度限制的簡單方法是使用關鍵 ID 和上次使用時間戳記的表。表的大小可能有限,但至少可容納 16 個條目。如果表已滿且沒有條目可以被更新或丟棄,則安全硬體實現“故障安全”,寧願拒絕所有速度受限的金鑰操作,直到條目之一到期。所有條目在重新啟動後過期是可以接受的。

也可以使用TAG::MAX_USES_PER_BOOT限制每次啟動時密鑰的使用次數。這還需要一個追蹤表,該表至少可容納四個鍵並且還可以安全地進行故障保護。請注意,應用程式將無法建立每次啟動受限的密鑰。此功能不會透過 Keystore 公開,而是為系統操作保留的。

此功能不會向應用程式公開。

隨機數產生器重新播種

由於安全硬體為金鑰材料和初始化向量(IV) 產生隨機數,並且由於硬體隨機數產生器可能並不總是完全值得信賴,因此Keymaster HAL 提供了一個接口,允許客戶端提供額外的熵,該熵將混合到隨機數中。產生的數字。

使用硬體隨機數產生器作為主要種子來源。透過外部 API 提供的種子資料不能是用於數位產生的唯一隨機來源。此外,如果任何一個種子來源是不可預測的,所使用的混合操作需要確保隨機輸出是不可預測的。

此功能不會向應用程式公開,但由框架使用,該框架定期向安全硬體提供從 Java SecureRandom 實例檢索的附加熵。