TPM 安全¶
本文件的目的是描述我們如何使核心對 TPM 的使用在面對外部窺探和資料包篡改攻擊(文獻中稱為被動和主動中間人攻擊)時保持相當的健壯性。當前的安全文件適用於 TPM 2.0。
引言¶
TPM 通常是透過某種低頻寬匯流排連線到 PC 的獨立晶片。也有例外,例如 Intel PTT,它是在靠近 CPU 的軟體環境中執行的軟體 TPM,這些會受到不同的攻擊,但目前,大多數加固的安全環境需要一個獨立的硬體 TPM,這也是本文討論的使用場景。
總線上的窺探和篡改攻擊¶
當前窺探的最新技術是 TPM Genie 硬體中間人裝置,它是一個簡單的外部裝置,可以在幾秒鐘內安裝到任何系統或筆記型電腦上。最近,針對 Windows Bitlocker TPM 系統的攻擊成功演示。最近,針對 基於 TPM 的 Linux 磁碟加密方案的相同攻擊也發生了。下一階段的研究似乎是入侵總線上現有裝置以充當中間人,因此攻擊者需要物理訪問幾秒鐘的事實可能不復存在。然而,本文件的目標是在這種環境下盡我們所能地保護 TPM 秘密和完整性,並嘗試確保如果我們無法阻止攻擊,至少我們可以檢測到它。
不幸的是,TPM 的大部分功能,包括硬體重置功能,都可以被有權訪問匯流排的攻擊者控制,因此我們將在下面討論一些中斷的可能性。
測量 (PCR) 完整性¶
由於攻擊者可以向 TPM 傳送自己的命令,他們可以傳送任意的 PCR 擴充套件,從而破壞測量系統,這將是一個令人討厭的拒絕服務攻擊。然而,還有兩種更嚴重的攻擊,旨在針對與信任測量密封的實體。
攻擊者可以攔截來自系統的所有 PCR 擴充套件並完全替換為他們自己的值,從而重播一個未篡改的狀態,這將導致 PCR 測量證明一個受信任的狀態並釋放秘密。
在某個時刻,攻擊者可以重置 TPM,清除 PCRs,然後傳送他們自己的測量值,這將有效地覆蓋 TPM 已經完成的啟動時間測量值。
第一種可以透過始終對 PCR 擴充套件和讀取命令進行 HMAC 保護來阻止,這意味著測量值無法在不產生可檢測的響應中 HMAC 失敗的情況下被替換。然而,第二種只能透過依賴某種機制來檢測,這種機制會在 TPM 重置時發生變化。
秘密保護¶
進出 TPM 的某些資訊,例如金鑰密封、私鑰匯入和隨機數生成,容易受到攔截,而單獨的 HMAC 保護無法阻止,因此對於這些型別的命令,我們還必須採用請求和響應加密以防止秘密資訊的丟失。
建立與 TPM 的初始信任¶
為了從一開始就提供安全性,必須建立一個初始的共享或非對稱秘密,這個秘密也必須不為攻擊者所知。最明顯的途徑是背書和儲存種子,它們可以用來派生非對稱金鑰。然而,使用這些金鑰很困難,因為將它們傳遞到核心的唯一方法是在命令列上,這需要啟動系統中的廣泛支援,並且不能保證任一層次結構都沒有某種授權。
Linux 核心選擇的機制是使用標準儲存種子引數從空種子派生主橢圓曲線金鑰。空種子有兩個優點:首先,該層次結構在物理上不能有授權,所以我們總是可以使用它;其次,空種子在 TPM 重置時會改變,這意味著如果我們在一天開始時在空種子上建立信任,那麼如果 TPM 重置並且種子改變,所有用派生金鑰加鹽的會話都將失敗。
顯然,在沒有其他先前共享秘密的情況下使用空種子,我們必須建立並讀取初始公鑰,這當然可能被匯流排中間人攔截和替換。然而,TPM 有一個金鑰認證機制(使用 EK 背書證書,建立證明身份金鑰並用該金鑰認證空種子主金鑰),這在核心內部執行過於複雜,因此我們保留一份空主金鑰名稱的副本,透過 sysfs 匯出,以便使用者空間在啟動時可以執行完整的認證。這裡的確定性保證是,如果空主金鑰認證正確,您就知道自當天開始以來所有的 TPM 事務都是安全的;如果認證不正確,您就知道您的系統上存在中間人(並且在啟動期間使用的任何秘密都可能已經洩露)。
信任堆疊¶
在當前的空主金鑰方案中,TPM 必須在移交給下一個消費者之前完全清除。然而,核心將派生的空種子金鑰的名稱交給使用者空間,然後使用者空間可以透過認證來驗證。因此,這種名稱移交鏈也可以用於各種引導元件之間(透過未指定的機制)。例如,grub 可以使用空種子方案來確保安全,並將名稱移交給引導區域中的核心。核心可以自己派生金鑰和名稱,並且明確地知道如果它們與移交的版本不同,則發生了篡改。因此,透過名稱移交,將任意引導元件(UEFI 到 grub 到核心)連結起來成為可能,前提是每個後續元件都知道如何收集名稱並根據其派生的金鑰進行驗證。
會話屬性¶
核心使用的所有 TPM 命令都允許會話。HMAC 會話可用於檢查請求和響應的完整性,解密和加密標誌可用於保護引數和響應。HMAC 和加密金鑰通常從共享授權秘密派生,但對於許多核心操作,這都是眾所周知的(並且通常為空)。因此,核心使用的每個 HMAC 會話都必須使用空主金鑰作為鹽金鑰建立,從而為會話金鑰派生提供加密輸入。因此,核心一次建立空主金鑰(作為易失性 TPM 控制代碼),並將其儲存在 tpm_chip 中儲存的上下文中,以供每次核心內使用 TPM。目前,由於核心內資源管理器中缺乏去間隙處理,每個操作都必須建立和銷燬會話,但在未來,單個會話也可以重複用於核心內 HMAC、加密和解密會話。
保護型別¶
對於每個核心內操作,我們都使用空主金鑰加鹽的 HMAC 來保護完整性。此外,我們使用引數加密來保護金鑰密封,使用引數解密來保護金鑰解封和隨機數生成。
使用者空間中的空主金鑰認證¶
每個 TPM 都附帶幾個用於主背書金鑰的 X.509 證書。本文件假定證書的橢圓曲線版本存在於 01C00002,但也同樣適用於 RSA 證書(在 01C00001)。
認證的第一步是使用 TCG EK 憑證配置檔案中的模板建立主金鑰,這允許將生成的主金鑰與證書中的金鑰進行比較(公鑰必須匹配)。請注意,EK 主金鑰的生成需要 EK 層次結構密碼,但 EC 主金鑰的預生成版本應存在於 81010002,並且可以在其上執行 TPM2_ReadPublic(),無需金鑰許可權。接下來,必須驗證證書本身是否鏈回到製造商根(應在製造商網站上釋出)。完成此操作後,在 TPM 內部生成一個證明金鑰 (AK),並且可以使用其名稱和 EK 公鑰透過 TPM2_MakeCredential 加密一個秘密。然後 TPM 執行 TPM2_ActivateCredential,只有當 TPM、EK 和 AK 之間的繫結為真時,它才會恢復秘密。生成的 AK 現在可用於執行核心已匯出的空主金鑰的認證。由於 TPM2_MakeCredential/ActivateCredential 有些複雜,因此下面描述了一個涉及外部生成的私鑰的更簡化過程。
這個過程是通常基於隱私 CA 的證明過程的簡化縮寫。這裡的假設是證明是由 TPM 所有者完成的,因此所有者只能訪問所有者層次結構。所有者建立一對外部公鑰/私鑰(此處假定為橢圓曲線),並使用內部包裝過程將私鑰包裝以進行匯入,並將其父級設定為 EC 派生的儲存主金鑰。TPM2_Import() 使用一個引數解密 HMAC 會話完成,該會話用 EK 主金鑰加鹽(也不需要 EK 金鑰許可權),這意味著內部包裝金鑰是加密引數,因此除非 TPM 擁有經過認證的 EK,否則 TPM 將無法執行匯入,因此如果命令成功並且返回時 HMAC 驗證,我們知道我們有一個僅適用於經過認證的 TPM 的可載入私鑰副本。此金鑰現在已載入到 TPM 中,並且儲存主金鑰已重新整理(以釋放空金鑰生成空間)。
現在使用 TCG TPM v2.0 供應指南中概述的儲存配置檔案生成空 EC 主金鑰;計算此金鑰的名稱(公共區域的雜湊)並與核心在 /sys/class/tpm/tpm0/null_name 中提供的空種子名稱進行比較。如果名稱不匹配,則 TPM 已被篡改。如果名稱匹配,使用者執行 TPM2_Certify(),使用空主金鑰作為物件控制代碼,載入的私鑰作為簽名控制代碼,並提供隨機限定資料。返回的 certifyInfo 的簽名將與載入的私鑰的公共部分進行驗證,並檢查限定資料以防止重放。如果所有這些測試都透過,使用者現在可以確信此核心的整個啟動序列中 TPM 的完整性和隱私性得到了保持。