在過去的幾年中,影響電腦開機方式的攻擊數量有所增加。大多數現代電腦使用的規格稱為整合可延伸韌體介面 (UEFI),它在作業系統(例如 Windows)和平台韌體(例如,磁碟機,視訊卡)之間定義了一個軟體介面。UEFI 內建了安全性機制,可確保平台韌體能夠透過稱為開機載入器的應用程式進行密碼編譯驗證,並安全地開機。此韌體儲存在主機板上的非揮發性 SPI 快閃記憶體中,因此即使重新安裝作業系統並更換磁碟機,它仍會保留在系統上。

這會建立一個「信任錨」,可用來驗證開機程序的每個階段,但遺憾的是,這個信任錨也是攻擊的目標。在這些 UEFI 攻擊中,惡意動作會在開機程序早期載入到遭入侵的裝置上。這意味著惡意程式碼可以變更設定資料,透過「植入」它本身來建立持久性,並可以繞過僅在作業系統階段才會載入的安全措施。因此,雖然 UEFI 錨定的安全開機可以保護開機載入器免受開機載入器攻擊,但它不會保護 UEFI 韌體本身。
由於這種不斷增長的攻擊趨勢,我們開始了密碼編譯簽署 UEFI 韌體的程序,作為一種緩解措施。雖然我們現有的解決方案是 x86 AMD 伺服器系列特定的平台,但我們沒有與針對 Arm 的 UEFI 韌體簽署類似的解決方案。為了確定缺少的內容,我們必須對 Arm 安全開機程序進行深入研究。
請繼續閱讀,以瞭解 Arm 受信任韌體安全開機的世界。
ARM 受信任韌體安全開機
Arm 透過稱為受信任主機板開機需求 (TBBR) 或 Arm 受信任韌體 (ATF) 安全開機的架構,定義了一個信任式開機程序。TBBR 的運作方式是驗證一系列密碼編譯簽署的二進位映像檔,每個映像檔都包含系統開機程序中要載入和執行的不同階段或元素。每個開機載入器 (BL) 階段都在初始化程序中完成一個不同的階段:
BL1BL1 定義開機路徑(這是冷開機還是暖開機)、初始化架構(例外向量,CPU 初始化和控制暫存器設定),並初始化平台(啟用看門狗程序、MMU 和 DDR 初始化)。
BL2BL2 準備 Arm 受信任韌體 (ATF) 的初始化,該堆疊負責設定安全開機程序。ATF 設定後,即會初始化控制台,對應 MMU 的記憶體,並為下一個開機載入器設定訊息緩衝區。
BL3BL3 階段包含多個部分,第一部分是初始化在偵測系統拓撲中使用的執行階段服務。初始化之後,在 ATF「安全區域」開機階段到「標準區域」開機階段之間有一個遞交,其中包括設定 UEFI 韌體。設定內容是為了確保安全狀態資訊不會進入標準區域執行狀態。
每個映像檔都由一個公開金鑰進行驗證,該金鑰儲存在已簽署的憑證中,並可以追蹤到儲存在一次性可程式化 (OTP) 記憶體或 ROM 中的 SoC 上的根金鑰。
TBBR 最初是為手機設計的。它建立了一個參考架構,向我們展示了如何從執行的第一個 ROM (BL1) 到遞交再到「標準區域」韌體 (BL3) 構建一個「信任鏈結」。雖然這建立了一個經過驗證的韌體簽署鏈結,但有幾點需要注意:
SoC 製造商在安全開機鏈結中參與較多,而客戶幾乎沒有參與。
每個客戶需要一個唯一的 SoC SKU。若是一個客戶,這可能很容易,但是大多數製造商擁有數千個 SKU
SoC 製造商主要負責 PKI 鏈結的端對端簽署和維護。這就為需要 USB 金鑰鏈進行簽署的程序增加了複雜性。
不能在製造商之外擴展。
這告訴我們,為手機構建的功能不能針對伺服器進行擴展。
如果我們 100% 參與了製造過程,這就不是什麼大問題,但我們是客戶和消費者。身為客戶,我們對我們的伺服器和區塊設計有很大的控制權,因此我們尋找了設計合作夥伴,他們會採用我們能夠使用 AMD 平台安全開機實作的一些概念,並對其進行改進以適應 Arm CPU。

提升效能
我們與 Ampere 合作,並測試了他們的 Altra Max 單一插槽機架式伺服器 CPU(代碼名為 Mystique),它所提供的超高效能以及每個核心極高的電源效率,正是我們在降低功耗方面所夢寐以求的。這些不過是零光片羽,重點是 Ampere 將各種功能向後移植到了 Altra Max 中,特別是理論式攻擊緩解措施,其中包括來自 Armv8.5 指令集架構的 Meltdown 和 Spectre(變體 1 和變體 2),從而為 Altra 的 ISA 贏得了「+」認證。
Ampere 實作的已簽署開機程序確實上述 ATF 簽署程序類似,但有一些細微的變化。我們將對其略作解釋,以幫助為我們所做的修改設定內容。

Ampere 安全開機
上圖顯示的是由 Ampere 實作的 Arm 處理器開機順序。系統控制處理器 (SCP) 由系統管理處理器 (SMpro) 和電源管理處理器 (PMpro) 組成。SMpro 負責安全開機和 bmc 通訊等功能,而 PMpro 負責動態頻率調整和晶片上熱監控等電源功能。
在上電復位時,SCP 會從 ROM 執行系統管理開機載入器,並載入 SMpro 韌體。初始化之後,SMPro 會在 PMpro 和 ATF 執行緒上產生電源管理堆疊。ATF BL2 和 BL31 會顯示處理器資源,如 DRAM 和 PCIe。然後,控制會傳遞到 BL33 BIOS。
驗證流程
開啟電源時,SMpro 韌體會從 SCP EEPROM 的 SMpro 金鑰憑證讀取 Ampere 的公開金鑰 (ROTPK),計算雜湊值,並將其與 eFuse 中儲存的 Ampere 公開金鑰雜湊值進行比較。通過驗證後,Ampere 的公開金鑰會用來解密 SMpro、PMpro 和 ATF 韌體的金鑰和內容憑證,這些憑證會依照上述順序啟動。

SMpro 公開金鑰將用於驗證 SMpro 和 PMpro 映像檔和 ATF 金鑰,它們會依次驗證 ATF 映像檔。這種串聯驗證集源於 Ampere 根金鑰,並儲存在稱為電子保險絲 (eFuse) 的芯片中。一個 eFuse 只能程式化一次,將內容設為唯讀,且不能竄改,也不能修改。
這是用於簽署系統安全區域韌體的原始硬體信任根目錄。當我們考慮這一點時,在參照用於 AMD PSB 的簽署程序並且知道 SoC 內有足夠大的一次性可程式化 (OTP) 區域之後,我們想:為什麼不能在這裡插入金鑰雜湊呢?
單一網域安全開機

單一網域安全開機採用相同的驗證流程,並將客戶公開金鑰(在本例中為 Cloudflare 韌體簽署金鑰)的雜湊加入到 eFuse 網域。這可透過硬體信任根目錄驗證 UEFI 韌體。此程序由 BL2 在已驗證的 ATF 韌體中執行。從 UEFI 安全變數儲存體中讀取我們的公開金鑰 (dbb)、計算雜湊值並將其與 eFuse 中儲存的公開金鑰雜湊值進行比較。如果相符,則已驗證的公開金鑰會用來解密 BL33 內容憑證,從而驗證並啟動 BIOS,以及剩餘的開機項目。這是 SDSB 新增的主要功能。它使用處理器上的單一 eFuse 信任根目錄來驗證整個軟體開機鏈結。
構建區塊
在對單一網域安全開機的工作原理有了基本的瞭解後,下一個問題自然就是「如何實作它?」。我們確保在構建時已簽署所有 UEFI 韌體,但如果分解為幾個步驟,則可以更好地理解此程序。
我們的原設備製造商 (ODM) Ampere 和我們在 SDSB 的執行中發揮了作用。首先,我們使用內部的安全 PKI 為公開-私密金鑰組產生憑證。公開金鑰端以 UEFI 安全變數格式的 dbb.auth 和 dbu.auth 提供給 ODM。Ampere 為 ODM 提供參考軟體發行套件 (SRP),包括基礎板管理控制器、系統控制處理器、UEFI 和複雜的可程式邏輯元件 (CPLD) 韌體,而 ODM 可針對自己的平台進行自訂。ODM 會產生描述硬體設定的主機板檔案,還會自訂 UEFI 以在第一次開機時將 dbb 和 dbu 註冊至安全變數儲存體。

完成上述步驟後,我們使用 ODM 的 UEFI ROM 映像檔(Arm 受信任韌體 (ATF) 和主機板檔案)產生一個 UEFI.slim 檔案。(注意:這與 AMD PSB 不同之處在於,會簽署整個映像檔和 ATF 檔案;而 AMD PSB,只會簽署第一個開機碼區塊。)整個 .SLIM 檔案使用我們的私密金鑰簽署,從而在檔案中產生一個簽章雜湊。這只能使用正確的公開金鑰進行驗證。最後,ODM 會將 UEFI 封裝為與其平台 BMC 相容的 .HPM 格式。
同時,我們會提供 DER 格式的公開金鑰的偵錯保險絲選擇和雜湊值。Ampere 使用此資訊建立一個特殊版本的 SCP 韌體,稱為安全佈建 (SECPROV) .slim 格式。此韌體僅執行一次,以將偵錯保險絲設定和公開金鑰雜湊以程式設計到 SoC eFuse 中。Ampere 將 SECPROV .slim 檔案提供給 ODM,而 ODM 將其封裝到一個 .hpm 檔案(與 BMC 韌體更新工具相容)中。
熔斷金鑰

在系統製造過程中,會將韌體預先程式設計到儲存體 IC 中,然後再放到主機板上。請注意,SCP EEPROM 包含 SECPROV 映像檔,而不是標準 SCP 韌體。第一次開啟系統電源之後,會將一個 IPMI 命令傳送至 BMC,而 BMC 會將 Ampere 處理器從復位中釋放。這讓 SECPROV 韌體可以執行,並使用我們的公開金鑰雜湊和偵錯保險絲設定燒錄 SoC eFuse。

最終製造流程

佈建公開金鑰後,製造就會繼續使用標準韌體重新對 SCP EEPROM 進行程式設計。在系統開啟電源後,ATF 會偵測到安全變數儲存體中沒有金鑰,並允許 UEFI 韌體開機,而不管是否已簽署。由於這是第一次 UEFI 開機,它會將我們的公開金鑰程式設計到安全變數儲存體中並重新開機。ATF 像往常一樣由 Ampere 的公開金鑰雜湊驗證。由於我們的公開金鑰存在於 dbb 中,因此會根據 eFuse 中的公開金鑰雜湊進行驗證,並允許 UEFI 開機。
驗證

驗證的第一部分需要觀察到 eFuse 成功解構。這會將我們的公開金鑰雜湊壓印到一個專用的不可變的記憶體區域,以便禁止覆寫該雜湊。自動或手動向 BMC 發出 IPMI OEM 命令時,BMC 會觀察到來自 SECPROV 韌體的訊號,表示 eFuse 程式設計完成。這可以使用 BMC 命令來探查。
在 eFuse 燒斷後,驗證會透過觀察其他韌體的開機鏈結來繼續。SCP、ATF 或 UEFI 韌體損毀會妨礙開機流程和開機驗證,並導致機器無法開機到作業系統。韌體就緒後,就可以從啟動機器開始進行路徑驗證了。

第一次開機時,韌體會以下列順序開機:BMC、SCP、ATF 和 UEFI。BMC、SCP 和 ATF 韌體可透過各自的序列主控台觀察到。UEFI 會自動將 dbb 和 dbu 檔案註冊至安全變數儲存體,並觸發系統重設。
觀察到重設後,如果功能正確執行,機器應該成功開機至作業系統。為了進一步驗證,我們可以使用 UEFI 殼層環境來擷取 dbb 檔案,並將雜湊與提交給 Ampere 的雜湊值進行比較。成功驗證金鑰後,我們會刷新一個未簽署的 UEFI 映像檔。未簽署的 UEFI 映像檔會造成驗證在開機載入器階段 BL3-2 失敗。因此,ATF 韌體會經歷一個開機迴圈。如果使用不正確的金鑰簽署 UEFI 映像檔,會出現類似的結果。

更新的驗證流程
在所有後續的開機循環中,ATF 會讀取安全變數 dbb(我們的公開金鑰)、計算金鑰的雜湊值,並將其與 eFuse 中的唯讀 Cloudflare 公開金鑰雜湊值進行比較。如果計算的雜湊值和 eFuse 雜湊值相符,則我們的公開金鑰變數會受到信任,並用來驗證已簽署的 UEFI。之後,系統會開機到作業系統。
我們來開機吧!
由於我們在構建時設定了 eFuse,因此我們無法獲得一台未啟用該功能的機器來示範該功能的設定,但是我們可以示範在未簽署 BIOS 和已簽署 BIOS 之間的情況。我們在設定該功能時會觀察到的是一個自訂 BMC 命令,用於指示 SCP 將 ROTPK 燒錄到 SOC 的 OTP 保險絲中。從那裡,我們會觀察到對 BMC 的回饋,其中詳細說明了燒錄保險絲是否成功。第一次啟動 UEFI 映像檔時,UEFI 會將 dbb 和 dbu 寫入到安全儲存體中。
正如您所看到的,在刷新未簽署的 BIOS 之後,機器無法開機了。

儘管在開機失敗時缺少可見度,但有些事情正在內部發生。SCP(系統控制處理器)仍會開機。
SCP 映像檔保存著一個帶有 Ampere 產生的 ROTPK 和 SCP 金鑰雜湊值的金鑰憑證。SCP 將計算 ROTPK 雜湊值,並將其與燒錄的 OTP 保險絲進行比較。如果失敗,即雜湊值不符,您會觀察到一個如上所示的失敗。如果成功,則 SCP 韌體將會繼續啟動 PMpro 和 SMpro。PMpro 和 SMpro 韌體都會經過驗證,並繼續進行 ATF 驗證流程。
SCP 驗證的結果是透過 SCP HOB(遞交區塊)將 BL1 金鑰傳遞至第一階段的開機載入器,以繼續前面提到的標準三階段開機載入器 ATF 驗證。
在 BL2,會從安全變數儲存體讀取 dbb,並用它來驗證 BL33 憑證,然後透過啟動 BL33 UEFI 映像檔來完成開機程序。
前路漫漫
近年來,像 BMC 這樣的伺服器上的管理介面一直是網路攻擊(包括勒索軟體、植入和干擾性作業)的目標。對 BMC 的存取可以是本機,也可以是遠端。遠端向量開啟時,可能會透過網路介面,在 BMC 上安裝惡意軟體。入侵 BMC 上的軟體後,惡意軟體或間諜軟體就可以持續存在於伺服器上。攻擊者可以直接使用刷新工具(例如 flashrom 或 socflash)更新 BMC,而無需在 UEFI 層級建立相同的韌體復原能力。
未來會涉及使用與主機 CPU 無關的基礎結構,在開機時間之前啟用具有密碼編譯安全的主控件。我們將尋求採用一種由 Open Compute Project 的資料中心安全控制模組規格 (DC-SCM) 2.0 規格提出的模組化方法。憑藉該方法,我們可以實現信任根目錄標準化,簽署 BMC,並為元件和週邊設備指派基於實體不可複製功能 (PUF) 的身分識別金鑰,來限制使用 OTP 熔斷。OTP 熔斷在嘗試「電子循環」或重複使用機器時會產生問題,因為您無法真正刪除機器身分識別。