13.1 安全開機

在 UEFI 的領域里,保護開機程序即表示建立一條信任鏈。平台是此信任鏈的根;在 SUSE Linux Enterprise 的網路位置中,主機板和板載韌體可視為平台。或者換另一種說法,它就是硬體廠商,信任鏈由該硬體廠商流向元件製造商、作業系統廠商等。

信任透過公用金鑰加密來表示。硬體廠商將所謂的「平台金鑰 (PK)」放入韌體中,表示信任的根。與作業系統廠商及其他的信任關係透過使用「平台金鑰」簽署其金鑰加以記錄。

最後,要求任何程式碼必須由其中一個信任金鑰簽署後,韌體才將執行程式碼,以此構建安全性 — 可以是作業系統開始載入程式、位於某些 PCI Express 卡之快閃式記憶體內或磁碟上的一些驅動程式,也可以是韌體本身的更新。

實質上,若要使用安全開機,則需要使用韌體信任的金鑰簽署作業系統載入程式,並且需要作業系統載入程式來驗證其載入的核心是否受信任。

金鑰交換金鑰 (KEK) 可新增至 UEFI 金鑰資料庫。這樣一來,您便可以使用其他證書,只要這些證書是以 PK 的私密部分簽署的即可。

13.1.1 在 SUSE Linux Enterprise 上實作

預設會安裝 Microsoft 的金鑰交換金鑰 (KEK)。

預設已在 UEFI/x86_64 安裝中啟用安全開機功能。可以在開機載入程式設定對話方區塊的開機碼選項索引標籤中找到啟用安全開機支援選項。該選項支援在韌體中啟用安全開機後開機,同時也支援在停用安全開機後開機。

圖 13-1 安全開機支援

安全開機功能要求 GUID 分割區表 (GPT) 以主開機記錄 (MBR) 取代舊分割區。如果 YaST 在安裝期間偵測到 EFI 模式,它將會嘗試建立 GPT 分割區。UEFI 需要在 FAT 格式 EFI 系統分割區 (ESP) 上找到 EFI 程式。

支援 UEFI 安全開機本質上需要具有韌體辨識為信任金鑰之數位簽名的開機載入程式。為了對 SUSE Linux Enterprise 客戶有幫助,韌體先天地信任該金鑰,不需要任何手動介入。

實現此目的方法有兩種。一種方法是與硬體廠商協作,讓他們簽署一個 SUSE 金鑰,隨後 SUSE 會使用它來簽署開機載入程式。另一種方法是執行 Microsoft 的 Windows Logo Certification 程式認證開機載入程式,並讓 Microsoft 辨識 SUSE 簽署金鑰 (即,使用其 KEK 進行簽署)。目前,SUSE 透過 UEFI 簽署服務 (在此範例中為 Microsoft) 來簽署載入程式。

圖 13-2 UEFI:安全開機程序

SUSE 在實作層使用預設安裝的 shim 載入程式。這是一個智慧型解決方案,它可避免法律問題並大大簡化了認證和簽署步驟。shim 載入程式的工作是載入開機載入程式 (例如 GRUB 2) 並對它進行驗證;此開機載入程式接著會僅載入 SUSE 金鑰簽署的核心。SUSE 從全新安裝的 SLE11 SP3 開始提供此功能,並啟用 UEFI 安全開機。

信任使用者的類型有兩種:

  • 第一種是擁有金鑰的使用者。平台金鑰 (PK) 幾乎允許所有作業。金鑰交換金鑰 (KEK) 允許 PK 允許的所有作業,變更 PK 除外。

  • 第二種是擁有實際存取機器權限的任何人。擁有實際存取機器權限的使用者可以將機器重新開機並設定 UEFI。

UEFI 提供兩種類型的變數來滿足那些使用者的需求:

  • 第一種是所謂的已驗證變數,這些變數可透過開機程序 (所謂的「開機服務環境」) 和執行中的作業系統進行更新,但前提是使用簽署變數舊值的金鑰來簽署變數的新值。並且它們只能附加至或變更為序號更高的值。

  • 第二種稱為僅開機服務變數。開機程序期間執行的所有程式碼都可以存取這些變數。在開機程序結束之後並在作業系統啟動之前,開機載入程式必須呼叫 ExitBootServices 呼叫。此後,這些變數無法再存取,且作業系統無法更改它們。

各種 UEFI 金鑰清單屬於第一種類型,因為此類型允許線上更新與新增金鑰、驅動程式和韌體指紋,以及將它們列入黑名單。第二類變數僅開機服務變數可協助以安全且開放原始碼友善的方式實作安全開機,因此可與 GPLv3 相容。

SUSE 以 shim 開始,它是一個小而簡單的 EFI 開機載入程式,最初由 Fedora 開發。它由 SUSE KEK 簽署的證書和 Microsoft 發放的證書共同簽署,以系統上 UEFI 金鑰資料庫中可用的 KEK 為基礎。

這允許 shim 載入並執行。

shim 隨後會繼續驗證它要載入的開機載入程式是否受信任。在預設情況下,shim 將會使用內嵌於其主體的獨立 SUSE 證書。此外,shim 將允許註冊額外的金鑰,並覆寫預設的 SUSE 金鑰。在下文中,我們稱它們為機器擁有者金鑰,或簡稱為 MOK。

接著,開機載入程式會在驗證核心後將其開機,核心繼而將對模組執行同樣的操作。

13.1.2 MOK (機器擁有者金鑰)

如果使用者 (機器擁有者) 要取代開機程序的任何元件,將會使用機器擁有者金鑰 (MOK)。mokutils 工具將會協助簽署元件並管理 MOK。

shim 載入時,註冊程序便會開始將機器重新開機並中斷開機程序 (例如按某個鍵)。隨後,shim 將進入註冊模式,允許使用者以開機分割區上之檔案中的金鑰取代預設 SUSE 金鑰。如果使用者選擇這麼做,shim 隨後將會計算該檔案的雜湊,並將結果置於僅開機服務變數中。這允許 shim 偵測對開機服務以外之檔案所進行的任何變更,從而避免篡改使用者核准的 MOK 清單。

所有這些操作都在開機期間進行 — 現在僅執行已驗證的程式碼。因此,僅顯示於主控台中的使用者可以使用機器擁有者的金鑰組。它不能是可以遠端存取作業系統的惡意軟體或駭客,因為駭客或惡意軟體只能變更檔案,而無法變更儲存在僅開機服務變數中的雜湊。

開機載入程式一旦載入並經 shim 驗證,便會在要驗證核心時回呼 shim,以避免驗證碼重複。Shim 將對此使用相同的 MOK 清單,並通知開機載入程式是否可以載入該核心。

如此一來,您便可以安裝您自己的核心或開機載入程式。您只需要安裝一組新的金鑰,隨後真實存在於第一次重新開機期間,由此對它們進行授權。因為 MOK 是一個清單而不僅僅是一個 MOK,所以您可以從多個廠商建立 shim 信任金鑰,從而允許從開機載入程式進行雙重或多重開機。

13.1.3 將自訂核心開機

下文以 http://en.opensuse.org/openSUSE:UEFI#Booting_a_custom_kernel 為基礎。

安全開機不會阻止您使用自我編譯的核心。您必須使用您自己的證書簽署該核心,並讓韌體或 MOK 知道該證書。

  1. 建立用於簽署的自訂 X.509 金鑰和證書:

    openssl req -new -x509 -newkey rsa:2048 -keyout key.asc \
      -out cert.pem -nodes -days 666 -subj "/CN=$USER/"

    如需建立證書的詳細資訊,請參閱 http://en.opensuse.org/openSUSE:UEFI_Image_File_Sign_Tools#Create_Your_Own_Certificate

  2. 將金鑰和證書封裝成 PKCS#12 結構:

    openssl pkcs12 -export -inkey key.asc -in cert.pem \
      -name kernel_cert -out cert.p12
  3. 產生 NSS 資料庫以與 pesign 配合使用:

    certutil -d . -N
  4. 將 PKCS#12 中包含的金鑰和證書輸入到 NSS 資料庫中:

    pk12util -d . -i cert.p12
  5. 使用 pesign 以新簽名保護核心:

    pesign -n . -c kernel_cert -i arch/x86/boot/bzImage \
      -o vmlinuz.signed -s
  6. 列出核心影像上的簽名:

    pesign -n . -S -i vmlinuz.signed

    此時,您可以如一般方式在 /boot 中安裝核心。因為核心現在已有自訂簽名,所以需要將用於簽署的證書輸入到 UEFI 韌體或 MOK 中。

  7. 將證書轉換為 DER 格式以便輸入到韌體或 MOK 中:

    openssl x509 -in cert.pem -outform der -out cert.der
  8. 將證書複製到 ESP 以方便存取:

    sudo cp cert.der /boot/efi/
  9. 使用 mokutil 自動啟動 MOK 清單。

      • 將證書輸入到 MOK 中︰

        mokutil --root-pw --import cert.der

        --root-pw 選項可讓 root 使用者直接使用。

      • 檢查準備就緒、即待註冊的證書清單︰

        mokutil --list-new
      • 將系統重新開機;shim 應會啟動 MokManager。您需要輸入 root 密碼以確認將證書輸入到 MOK 清單中。

      • 檢查是否已註冊新輸入的金鑰。

        mokutil --list-enrolled
      • 或者,如果要手動啟動 MOK,請按照下面的程序操作:

        重新開機

      • 在 GRUB 2 功能表中,按「c」鍵。

      • 類型︰

        chainloader $efibootdir/MokManager.efi
        boot
      • 選取從磁碟註冊金鑰

      • 導覽到 cert.der 檔案並按 Enter

      • 遵循指示註冊金鑰。一般情況下,應按「0」後再按「y」進行確認。

        或者,韌體功能表可能提供將新金鑰新增至簽名資料庫的方法。

13.1.4 使用非內建的驅動程式

在已啟用安全開機的情況下進行安裝期間,不支援新增非現成驅動程式 (換言之,不是 SLE 隨附的驅動程式)。預設不信任用於 SolidDriver/PLDP 的簽署金鑰。

您可以透過兩種不同的方式,在啟用安全開機的情況下在安裝期間安裝協力廠商驅動程式。在這兩種情況下,都要:

  • 在安裝之前,透過韌體或系統管理工具將需要的金鑰新增至韌體資料庫。此選項取決於您具體所用的硬體。如需詳細資訊,請諮詢您的硬體廠商。

  • 使用 https://drivers.suse.com/ 上或您的硬體廠商提供的可開機驅動程式 ISO,於第一次開機時在 MOK 清單中註冊需要的金鑰。

若要使用可開機驅動程式 ISO 在 MOK 清單中註冊驅動程式金鑰,請執行以下步驟︰

  1. 將上述 ISO 影像燒錄到空白 CD/DVD 媒體中。

  2. 使用新的 CD/DVD 媒體開始安裝,並準備好標準的 SUSE Linux Enterprise 媒體或網路安裝伺服器的 URL。

    如果您要進行網路安裝,請使用 install= 選項在指令行上輸入網路安裝來源的 URL。

    如果您是從光學媒體安裝,安裝程式會先從驅動程式套件開機,然後要求您插入 SUSE Linux Enterprise 產品的第一張光碟。

  3. 安裝時將會使用包含已更新驅動程式的 initrd。

如需詳細資訊,請參閱https://drivers.suse.com/doc/Usage/Secure_Boot_Certificate.html

13.1.5 功能和限制

以安全開機模式開機時,將會套用以下功能:

  • 安裝到 UEFI 預設的開機載入程式位置,這是為了保留或還原 EFI 開機項目而採用的機制。

  • 透過 UEFI 重新開機。

  • 如果沒有可回復到的舊版 BIOS,Xen 監管程式將使用 UEFI 開機。

  • 支援 UEFI IPv6 PXE 開機。

  • UEFI 支援視訊模式,核心可以從 UEFI 取回視訊模式,以使用相同的參數設定 KMS 模式。

  • UEFI 支援從 USB 裝置開機。

以安全開機模式開機時,必須遵守以下限制:

  • 為了確保無法輕易規避安全開機,當在安全開機模式下執行時,系統會停用部分核心功能。

  • 必須簽署開機載入程式、核心和核心模組。

  • 將會停用 Kexec 和 Kdump。

  • 將會停用休眠 (暫停磁碟上的作業)。

  • 無法存取 /dev/kmem/dev/mem,即使以 root 使用者身分也不行。

  • 無法存取 I/O 埠,即使以 root 使用者身分也不行。所有 X11 圖形驅動程式都必須使用核心驅動程式。

  • 不允許透過 sysfs 存取 PCI BAR。

  • 無法使用 ACPI 中的 custom_method

  • 無法使用適用於 asus-wmi 模組的 debugfs。

  • acpi_rsdp 參數對核心沒有任何影響。