UEFI Secure Boot — kompleksowy poradnik oraz konfiguracja

Tagi: #<Tag:0x00007f53fbb8eba0>

W tym poradniku objaśnię działanie mechanizmu UEFI Secure Boot, dowiesz się jak działa wspomniane zabezpieczenie i jak je skonfigurować

Co to jest Secure Boot?

Secure Boot jest to mechanizm UEFI, który ma za zadanie weryfikować uruchamiane pliki wykonywanle podczas początkowej fazy rozruchu komputera. UEFI przy włączonym Secure Boot będzie w stanie uruchomić pliki wykonywalne, które są opatrzone odpowiednią sygnaturą cyfrową bądź suma kontrolna uruchamianego pliku znajduje się w bazie dozwolonych sygnatur i sum kontrolnych (db).

Jak działa Secure Boot?

Na początek dam trochę teorii, postaram się tutaj objaśnić działanie tego mechanizmu

:one: Ustawienia Secure Boot w UEFI

Ustawieniami Bezpiecznego Rozruchu (Secure Boot) zarządza się z poziomu ustawień UEFI, z poziomu UEFI można włączyć bądź wyłączyć Secure Boot lub zmienić stan tego mechanizmu. Secure Boot przyjmuje następujące stany:

  • Standard - tryb w którym bazy danych kluczy posiadają klucze zdefiniowane przez producenta.
  • User/Custom - tryb w którym bazy danych kluczy zawierają klucze zdefiniowane przez użytkownika (właściciela sprzętu).
  • Setup - tryb w którym bazy danych kluczy są puste i klucze można zdefiniować z poziomu systemu operacyjnego bez żadnej autoryzacji.

W większości płyt głównych jest możliwość edycji zawartości baz danych kluczy z poziomu ustawień UEFI (czyli możliwość wyczyszczenia bazy, wgrania własnych kluczy z zewnętrznego nośnika itp.) ale są pewne wyjątki gdzie nie ma takiej możliwości (spotkałem się z tym w starszych płytach głównych Lenovo i w laptopach Lenovo). W takich przypadkach aby móc zdefiniować własne klucze to trzeba przełączyć Secure Boot w stan Setup (co wiąże się z wyczyszczeniem wszystkich kluczy i dezaktywacją Secure Boot) a następnie z poziomu systemu przy pomocy odpowiednich narzędzi wgrać własne klucze do baz kluczy.

:two: Bazy danych kluczy Secure Boot

Mechanizm Secure Boot posiada następujące bazy danych kluczy publicznych:

  • PK - Platform Key - jest to miejsce na klucz główny mechanizmu Secure Boot, tym kluczem nie podpisuje się cyfrowo plików wykonywalnych. Jeżeli posiada się klucz prywatny, który odpowiada kluczowi publicznemu będącemu w PK to możemy z poziomu systemu przy pomocy odpowiedniego oprogramowania edytować wszystkie bazy kluczy, które są w Secure Boot.

  • KEK - Key-exchange Key - jest to miejsce na klucze, które są wykorzystywane do aktualizacji bazy sygnatur dozwolonych “db” i bazy sygnatur zabronionych “dbx”. Kluczami znajdującymi się w KEK można cyfrowo podpisywać pliki wykonywalne.

  • db - Allow Signature Database - jest to miejsce na klucze, którymi można cyfrowo podpisywać pliki wykonywalne - ta zmienna może zawierać dowolny miks kluczy publicznych, które będą respektowane przez Secure Boot. Baza “db” może też przechowywać sumy kontrolne plików wykonywalnych (suma kontrolna musi być podpisana cyfrowo kluczem znajdującym się w “KEK”). Plik wykonywalny, którego suma kontrolna znajduje się w “db” zostanie uruchomiony przez UEFI.

  • dbx - Forbid Signature Database - jest to miejsce na klucze i sumy kontrolne, które nie mogą być respektowane przez Secure Boot. Zazwyczaj w tym miejscu umieszcza się unieważnione klucze lub sumy kontrolne plików wykonywalnych, których UEFI ma nie uruchamiać. Często umieszcza się w “dbx” sumy kontrolne starych bootloaderów tak aby nie móc zrobić downgrade do starszego bootloadera i wykorzystać jakiś luk w bezpieczeństwie, które mogą się tam znajdywać.

:warning: UWAGA!!! - Baza kluczy PK na dłuższą metę nie może być pusta! Jeżeli baza kluczy PK jest pusta to mechanizm Secure Boot samoczynnie przełączy się w stan “Setup”.

Gdy Secure Boot jest w stanie “Setup” to jednocześnie jest wyłączony (czyli w zasadzie da się uruchomić każdy plik wykonywalny niezależnie czy jest podpisany czy nie) - wgranie klucza do bazy PK automatycznie przełączy Secure Boot w stan Custom (nazywany też stanem “User”), czyli po restarcie komputera UEFI nie uruchomi niepodpisanego odpowiednim kluczem pliku wykonywalnego lub którego suma kontrolna nie znajduje się w bazie dozwolonych sygnatur.

:three: Bootowanie komputera z włączonym UEFI Secure Boot

Aby plik wykonywalny został załadowany przez UEFI z włączonym Secure Boot musi ten plik spełnić jedno z tych wymagań:

  • Jest podpisany kluczem znajdującym się w “KEK”.
  • Jest podpisany kluczem znajdującym się w “db”.
  • Suma kontrolna pliku znajduje się w “db”.

Oraz plik wykonywalny musi zawsze spełnić niżej wymienione dwa warunki:

  • Klucz, którym jest plik podpisany NIE MOŻE znajdywać się w “dbx”.
  • Suma kontrolna pliku wykonywalnego NIE MOŻE znajdywać się w “dbx”.

Środowisko testowe

Na chwilę odbiegnę od tematu ale wolę już to od razu napisać. Na pewno mogą znaleźć się osoby, które zapytają czy da się przetestować Secure Boot na maszynie wirtualnej, odpowiedź to TAK - ja do tworzenia tego poradnika używałem VMware Workstation 16 Pro, tylko aby móc zdefiniować własne klucze trzeba stworzyć maszynę wirtualną najlepiej wybierając goszczony system jako Windows 10 x64

obraz_2021-07-17_151628

Następnie wybrać typ Firmware jako UEFI (obojętnie czy będzie zaznaczony Secure Boot czy nie, można potem to w ustawieniach zmienić)

obraz_2021-07-17_151747

i po stworzeniu maszyny wirtualnej trzeba przejść do configów tej maszyny (domyślnie VMware zapisuje pliki maszyny w katalogu Dokumenty aktualnie zalogowanego użytkownika) i należy edytować plik z rozszerzeniem .vmx

po otwarciu tego pliku konfiguracyjnego przy pomocy jakiegokolwiek edytora tekstu (np. Notepad++) należy na końcu dopisać następujące dwie linijki:

uefi.secureBoot.dbDefault.append = "FALSE"
uefi.allowAuthBypass = "TRUE"

:warning: UWAGA!!! Przed rozpoczęciem edycji pliku konfiguracyjnego maszyny zaleca się zamknięcie VMware poprzez naciśnięcie obraz_2021-07-17_153629.

następnie zapisać plik i można uruchomić maszynę wirtualną w trybie Firmware, robi się to w następujący sposób:

Po uruchomieniu maszyny wirtualnej w trybie Firmware należy wybrać opcję Enter Setup, jak widać na poniższym obrazku pojawiła się opcja konfiguracji Secure Boot (w VMware ogranicza się to do edycji baz kluczy)

obraz_2021-07-17_153853

obraz_2021-07-17_153941

Jest możliwość edytowania wybranej bazy kluczy - czyli można dodawać i usuwać klucze czy sumy kontrolne. (Usunięcie klucza PK spowoduje przełączenie Secure Boot w stan Setup).

Co będzie wymagane:

  • Komputer czy maszyna wirtualna z UEFI obsługująca Secure Boot.
  • Dystrybucja linuxa (może być ubuntu w wersji live).

Niestety Windows nie posiada żadnego intuicyjnego narzędzia, które pozwalałoby zarządzać mechanizmem Secure Boot czy podpisywać pliki wykonywalne.

Konfiguracja Secure Boot po stronie UEFI

Ja pokażę konfiguracje Secure Boot w której usuwamy wszystkie stockowe klucze - czyli z PK usuwamy klucz producenta, z KEK klucz Microsoftu oraz innych tam podmiotów, to samo robimy w przypadku db i dbx.

W większości płyt głównych w ustawieniach UEFI ustawienia Secure Boot znajdują się w zakładce Security, w niektórych płytach głównych nie ma możliwości edycji zawartości bazy kluczy więc trzeba przełączyć Secure Boot w stan Setup:

W laptopach ASUS jest możliwość edycji bazy kluczy z poziomu ustawień UEFI lub możliwość zmiany stanu Secure Boot:

Aby wgrać klucz z poziomu UEFI, potrzebujemy wygenerowanych kluczy publicznych w formacie X.509 (DER) i jakiś nośnik danych sformatowany do FAT32.

W przypadku VMware trzeba włączyć maszynę w trybie Firmware i wejść w zakładkę Enter Setup, następnie w zakładkę Secure Boot Configuration i wejść w każdą bazę kluczy i usunąć wszystkie znajdujące się tam klucze czy sumy kontrolne.

obraz_2021-07-17_173955

Należy nacisnąć spacje lub enter aby usunąć zaznaczony klucz publiczny z wybranej bazy. W zasadzie usunięcie samego PK przełączy Secure Boot w stan Setup ale lepiej opróżnić wszystkie bazy kluczy.

Po przełączeniu Secure Boot w stan Setup można przejść dalej.

Tworzenie kluczy Secure Boot i ich wgrywanie

Proces tworzenia i wgrywania kluczy będę demonstrował na Ubuntu 20.04 ale na innych dystrybucjach linuxa też powinno działać.

:one: Instalacja wymaganego oprogramowania

Będą wymagane tylko trzy pakiety do zainstalowania z apt, czyli: openssl, efitools i sbsigntool. Aby zainstalować te trzy wymienione należy wydać polecenie:

apt install openssl efitools sbsigntool

:two: Generowanie kluczy Secure Boot

Do wygenerowania kluczy użyję narzędzia openssl, do poprawnego działania Secure Boot trzeba w zasadzie wygenerować dwie pary kluczy RSA X.509 (czyli PK i KEK) ale ja pozwolę sobie wygenerować trzy pary kluczy RSA czyli PK, KEK i db.

PK:

openssl req -new -x509 -newkey rsa:4096 -subj "/CN=PK/" -keyout PK.key -out PK.crt -days 38000 -nodes -sha256

KEK:

openssl req -new -x509 -newkey rsa:4096 -subj "/CN=KEK/" -keyout KEK.key -out KEK.crt -days 38000 -nodes -sha256

db:

openssl req -new -x509 -newkey rsa:4096 -subj "/CN=db/" -keyout db.key -out db.crt -days 38000 -nodes -sha256

:three: Stworzenie i podpisywanie listy sygnatur

W przypadku chęci zaktualizowania baz kluczy z poziomu działającego systemu operacyjnego to trzeba stworzyć tzw. listę sygnatur. Do tworzenia list sygnatur wykorzystuje się narzędzie cert-to-efi-sig-list a do podpisywania list sygnatur wykorzystuje się narzędzie sign-efi-sig-list.

PK:

cert-to-efi-sig-list PK.crt PK.esl
sign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth

W przypadku, gdy Secure Boot jest w stanie Setup to listę sygnatur PK podpisuje się tym samym kluczem, który jest na liście sygnatur.

KEK:

cert-to-efi-sig-list KEK.crt KEK.esl
sign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth

Listę sygnatur KEK podpisuje się certyfikatem PK (i jego prywatnym odpowiednikiem).

db:

cert-to-efi-sig-list db.crt db.esl
sign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth

Listę sygnatur i sum kontrolnych db podpisuje się certyfikatem KEK (i jego prywatnym odpowiednikiem).

:four: Wgrywanie własnych kluczy do Secure Boot z poziomu systemu

Aby wgrać własne klucze do Secure Boot z poziomu systemu (czyli bez konieczności przechodzenia do ustawień UEFI) należy posłużyć się utworzonymi listami sygnatur oraz narzędziem efi-updatevar.

PK:

efi-updatevar -f PK.auth PK

KEK:

efi-updatevar -f KEK.auth KEK

db:

efi-updatevar -f db.auth db

W niektórych przypadkach czy w niektórych dystrybucjach linuxa może podczas aktualizacji bazy kluczy ukazać się taki błąd:

obraz_2021-07-17_203214

Oznacza to że jest ustawiony atrybut nietykalności (read-only), więc w takim przypadku należy wydać jedno z tych poleceń odpowiadającemu danej bazie kluczy:

chattr -i /sys/firmware/efi/efivars/PK-*
chattr -i /sys/firmware/efi/efivars/KEK-*
chattr -i /sys/firmware/efi/efivars/db-*

:warning: UWAGA!!! Po dodaniu klucza PK automatycznie Secure Boot przełącza się w stan User/Custom, czyli jeżeli Secure Boot jest włączony to aktualnie uruchomiony system nie zostanie załadowany - więc należy unikać od tej pory restartów lub w przypadku konieczności restartu to w UEFI wyłączyć Secure Boot.

:five: Wgrywanie własnych kluczy do Secure Boot z poziomu UEFI

Do wgrania kluczy z poziomu UEFI potrzebne będą klucze publiczne (PK, KEK i ewentualnie db) w formacie X.509 (.der) oraz jakiś nośnik danych (np. pendrive) sformatowany do FAT32. Do przekonwertowania certyfikatów cyfrowych z .cer do formatu X.509 .der użyję narzędzia openssl.

openssl x509 -outform DER -in PK.crt -out PK.der
openssl x509 -outform DER -in KEK.crt -out KEK.der
openssl x509 -outform DER -in db.crt -out db.der

Po wygenerowaniu publicznych odpowiedników w formacie X.509 można skopiować pliki .der na jakiś nośnik z systemem plików FAT32 (może być to też lokalizacja /boot/efi gdzie jest podmontowana partycja EFI z plikami .efi).

Następnie trzeba wejść w ustawienia UEFI do zakładki Secure Boot Configuration, na sam początek wybiorę PK

obraz_2021-07-17_205441

Następnie trzeba wybrać opcję Enroll PK

obraz_2021-07-17_205517

Potem wybrać opcję Enroll PK Using File i wybrać nośnik danych/partycję na, której znajduje się certyfikat cyfrowy PK w formacie X.509

obraz_2021-07-17_205620

i wybór zatwierdzić klawiszem Enter. Teraz wystarczy wybrać opcję Commit Changes and Exit.

obraz_2021-07-17_205729

I od tego momentu klucz znajduje się w bazie PK. Dokładnie tak samo robi się w przypadku innych baz kluczy (np. KEK, db czy dbx).

Podpisywanie dystrybucji Linuxa

Sposób podpisywania dystrybucji linuxa dzieli się na dwa sposoby:

  • Podpisywanie dystrybucji linuxa wspierającą Secure Boot (czyli Ubuntu czy Linux Mint).
  • Podpisywanie dystrybucji linuxa niewspierającą Secure Boot (np. Kali Linux lub inne mniej popularne)

:one: Zmiana Bootloadera

Niestety GRUB nie jest domyślnie przeznaczony do obsługi Secure Boot, próbowałem wielokrotnie znaleźć jakiś sposób na podpisanie modułów GRUBa itp. ale niestety nie udało mi się znaleźć działającego sposobu.

W przypadku Ubuntu czy Linux Mint jest taki wynalazek jak shim - jest to zmodyfikowany GRUB podpisany kluczami Microsoftu, który pozwala na wczytywanie Ubuntu czy Linux Mint z włączonym Secure Boot w stanie Standard (czyli posiadający klucze Microsoftu) - ale ja nie będę objaśniał działania shim’a i tzw. kluczy MOK (które NIE SĄ częścią Secure Boot) bo sam shim umożliwia wtedy bootowanie wszystkiego co jest podpisane kluczami Microsoftu i Canoncial. Pisząc ten poradnik chcę pokazać jak skonfigurować Secure Boot nad którym właściciel sprzętu ma kontrolę i ma możliwość decydowania co na komputerze może być uruchomione a jednocześnie odebrać tą możliwość Microsoftowi, producentowi płyty głównej czy innym podmiotom.

Bootloaderami, które obsługują Secure Boot są: rEFInd i systemd-boot - ja preferuję ten pierwszy czyli rEFInd więc na nim się skupię bo jest prosty w konfiguracji w przeciwieństwie do systemd-boot.

Instalacja rEFInd’a wykonuje się poleceniem apt:

apt install refind

Podczas instalacji rEFInd’a będzie pytanie czy od razu zainstalować rEFInd’a na partycji EFI i ustawić jako domyślny bootloader. Należy zaznaczyć TAK.

po restarcie komputera już od razu widać że domyślnie uruchamia się rEFInd - on nie generuje żadnych plików konfiguracyjnych jak GRUB, tylko on skanuje na bieżąco możliwe do uruchomienia pliki wykonywalne. Jak widać domyślnie zaznaczyła się możliwość zbootowania GRUB’a - więc trzeba strzałkami wybrać chęć zbootowania ubuntu (vmlinuz).

rEFInd zapamiętuje ostatnio wybraną opcje, ostatnio zaznaczony element jest ustawiony przy następnym bootowaniu jako domyślny.

Po uruchomieniu systemu trzeba pozbyć się GRUBa - trzeba wykonać jedno proste polecenie:

apt purge grub*

deinstalator GRUBa zapyta czy usunąć GRUB-a z /boot/grub - należy zaznaczyć TAK.

Niestety deinstalator GRUBa jest tak ułomny że nie usunie po sobie plików, które są na partycji EFI (/boot/efi/EFI) więc trzeba przejść do tej lokalizacji poleceniem cd i wyświetlić listę plików.

cd /boot/efi/EFI
ls

powinny zostać katalogi refind i tools, resztę można usunąć (jeżeli obok Linuxa byłby zainstalowany Windows to należy zostawić też katalogi BOOT i Microsoft), czyli wykonujemy polecenia:

rm -r /boot/efi/EFI/ubuntu
rm -r /boot/efi/EFI/BOOT

po całkowitym usunięciu GRUBa teraz zawsze system będzie uruchamiał się przez rEFInd’a. Jest też możliwość wyłączenia trybu graficznego (czyli aby rEFInd działał tylko w trybie tekstowym) oraz zmiany czasu, po którym zostanie wykonane automatyczne bootowanie (np. zmiana z 20 sekund na 3 sekundy) - tego typu zmiany dokonuje się w pliku /boot/efi/EFI/refind/refind.conf

włączenie trybu tekstowego odbywa się poprzez usunięcie “#” przed opcją textonly.

:two: Podpisywanie dystrybucji Linuxa wspierającą Secure Boot

Dotyczy to tylko dystrybucji, które korzystają z tzw. shim’a czyli wspierają Secure Boot - są to m. in. Ubuntu czy Linux Mint. Podpisywanie tego typu dystrybucji nie jest jakimś wielkim wyzwaniem. Dlaczego? Bo trzeba podpisać cyfrowo w zasadzie trzy pliki czyli:

  • refind_x64.efi
  • ext4_x64.efi
  • vmlinuz

Do złożenia odpowiednich sygnatur na plikach użyję narzędzia sbsign - jest to narzędzie przeznaczone do podpisywania binarnych plików wykonywalnych (takich jak chociażby .efi)

Składnia tego polecenia jest następująca:

sbsign --cert <ścieżka do certyfikatu> --key <ścieżka do klucza> <ścieżka do podpisywanego pliku> --output <ścieżka gdzie ma być zapisany podpisany plik>

Można do podpisywania plików wykonywalnych użyć klucza znajdującego się w db czy KEK. Nie wolno podpisywać kluczem PK, ponieważ UEFI nie zbootuje pliku podpisanego tym kluczem.

Podpisywanie rEFInd’a:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/refind/refind_x64.efi --output /boot/efi/EFI/refind/refind_x64.efi

Podpisywanie modułu rEFInd’a, który dodaje obsługę ext4:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/refind/drivers_x64/ext4_x64.efi --output /boot/efi/EFI/refind/drivers_x64/ext4_x64.efi

Podpisywanie vmlinuz:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/vmlinuz-$(uname -r) --output /boot/vmlinuz-$(uname -r)

pozwoliłem dodać do polecenia $(uname -r) - w to miejsce system uzupełni wersję kernela - przez co nie trzeba będzie wchodzić w /boot i patrzeć jaką nazwę ma obecny kernel.

Po restarcie komputera i wydaniu polecenia:

mokutil --sb-state

otrzymujemy następujący rezultat:

obraz_2021-07-17_230336

Oznacza to, że Secure Boot jest aktywny.

Jeżeli system wyświetla komunikat, że nie istnieje polecenie mokutil to należy zainstalować ten pakiet poprzez polecenie apt install mokutil.

:warning: UWAGA!!! Co każdą aktualizację kernela będzie potrzeba ponownego złożenia podpisu na vmlinuz! W przeciwnym razie rEFInd nie będzie chciał załadować systemu. W przypadku aktualizacji rEFInda też będzie potrzeba ponownego podpisania bootloadera.

:three: Podpisywanie dystrybucji Linuxa niewspierającej Secure Boot

Są pewne dystrybucje Linuxa, które nie wspierają Secure Boot i ich konstrukcja jest taka że podpisanie tylko trzech rzeczy jak w Ubuntu nie wystarczy - tutaj trzeba będzie oczywiście podpisać bootloadera, kernela i jeszcze wszystkie moduły kernela.

Pokażę jak to zrobić na przykładzie Kali Linux - jest to idealny przykład, ponieważ on nie wspiera w żaden sposób Secure Boot i żaden moduł tego systemu nie jest podpisany jakimkolwiek kluczem.

W przypadku systemu, który nie wspiera Secure Boot to trzeba złożyć podpis na następujących plikach:

  • refind_x64.efi
  • ext4_x64.efi
  • vmlinuz
  • wszystkie moduły kernela

Podpisanie bootloadera i vmlinuz przebiega dokładnie tak samo jak w przypadku dystrybucji wspierające Secure Boot:

Podpisywanie rEFInd’a:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/refind/refind_x64.efi --output /boot/efi/EFI/refind/refind_x64.efi

Podpisywanie modułu rEFInd’a, który dodaje obsługę ext4:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/refind/drivers_x64/ext4_x64.efi --output /boot/efi/EFI/refind/drivers_x64/ext4_x64.efi

Podpisywanie vmlinuz:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/vmlinuz-$(uname -r) --output /boot/vmlinuz-$(uname -r)

Do podpisania wszystkich modułów potrzebne będą pliki źródłowe kernela - ponieważ w narzędziach dołączonych do plików źródłowych kernela jest jedno narzędzie, które pozwala podpisać moduły kernela. Aby umożliwić instalację plików źródłowych kernela należy edytować plik /etc/apt/sources.list i usunąć “#” przed deb-src

a następnie wydać polecenie apt update a następnie wydać polecenie:

apt install linux-headers-$(uname -r)

co spowoduje że dodatkowo zostanie pobrany kod źródłowy do aktualnego kernela i zostanie zapisany w /usr/src

Jeżeli już posiadamy kod źródłowy kernela wraz z narzędziami to można ponownie w /etc/apt/sources.list postawić “#” przed deb-src - ponieważ nie ma sensu aby co każdą aktualizacje kernela był pobierany kod źródłowy.

Do podpisu modułów będzie potrzebny klucz publiczny w formacie X.509 (.der), jeżeli wcześniej klucz nie został utworzony to jeszcze raz dam polecenie do przekształcenia klucza publicznego (.crt) na X.509:

openssl x509 -outform DER -in <certyfikat .crt> -out <certyfikat X.509 .der>

Podpisywanie wszystkich modułów kernela:

Do podpisania wszystkich modułów kernela stworzyłem jedno polecenie, które szuka plików z rozszerzeniem .ko w /lib/modules/<wersja kernela>/kernel i wszystkie pliki .ko podpisuje.

find /lib/modules/$(uname -r)/kernel -type f -name "*.ko" -exec /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 <klucz prywatny> <klucz publiczny w formacie X.509 (.der)> {} \;

W miejsca <klucz prywatny> i <klucz publiczny w formacie X.509 (.der)> należy wstawić ścieżki do kluczy Secure Boot. W moim przypadku polecenie wygląda tak:

find /lib/modules/$(uname -r)/kernel -type f -name "*.ko" -exec /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 /root/SecureBoot/db.key /root/SecureBoot/db.der {} \;

Po podpisaniu modułów należy zaktualizować obraz initrd, czyli trzeba wydać następujące polecenie:

update-initramfs -u

Od tego momentu system jest całkowicie podpisany, można włączyć Secure Boot czy dodać klucze do Secure Boot aby był w stanie User/Custom. Po wykonaniu restartu z włączonym Secure Boot i wykonaniu polecenia

mokutil --sb-state

uzyskałem następujący rezultat:

obraz_2021-07-18_004638

Czyli da się podpisać system, który w zasadzie nie wspiera Secure Boot.

:warning: UWAGA!!! Co każdą aktualizację kernela będzie potrzeba ponownego złożenia podpisu na vmlinuz! W przeciwnym razie rEFInd nie będzie chciał załadować systemu. W przypadku aktualizacji rEFInda też będzie potrzeba ponownego podpisania bootloadera. Modułów nie trzeba podpisywać co każdą aktualizacje kernela - jedynie trzeba podpisywać w przypadku dodania nowych modułów czy aktualizacji ich.

Kernel lockdown

Kernel Lockdown jest to mechanizm, który jest inicjowany gdy system zostanie uruchomiony przy włączonym SecureBoot. Ten mechanizm uniemożliwia:

  • Wczytywanie niepodpisanych modułów DKMS.
  • Wczytywanie niepodpisanych modułów jądra systemu (kernela).
  • Przełączenia komputera w tryb hibernacji.

ten mechanizm ma na celu zabezpieczyć przed próbą załadowania niechcianego kodu chociażby w przypadku gdy komputer jest w stanie hibernacji - ale ten mechanizm nie ma racji bytu w przypadku systemów zaszyfrowanych.

Tak wyglądają opcje zasilania przed włączeniem Secure Boot:

Tak wyglądają opcje zasilania po włączeniu Secure Boot:

obraz_2021-07-18_011500

Jak widać, jest różnica w dostępnych opcjach zasilania - a mianowicie zniknęła opcje hibernacji czy uśpienia hybrydowego. Są osoby, które korzystają z opcji hibernacji i dla nich Kernel Lockdown będzie zbyt inwazyjny.

Aby wyłączyć Kernel Lockdown trzeba dokonać zmian w configach kernela a następnie skompilować kernel - nie będę zamieszczał tutaj jak skompilować kernel bo jest to bardziej skomplikowana czynność.

Podpisywanie Windowsa

Są dwie metody dodania obsługi systemu Windows w przypadku customowego stanu Secure Boot, jeden to dodanie do bazy KEK kluczy Microsoftu ale to akurat nie jest trudne do zrobienia, ale ja skupię się na podpisanie zainstalowanego Windowsa własnymi kluczami, nie jest to trudne, ponieważ ogranicza się to do złożenia podpisu cyfrowego na czterech plikach:

  • bootmgfw.efi
  • bootmgr.efi
  • memtest.efi
  • bootx64.efi

Do złożenia podpisu będzie potrzebny system linux (może być wersja live), ponieważ Windows nie posiada żadnego wbudowanego oprogramowania do podpisywania plików wykonywalnych pod kątem Secure Boot.

Jeżeli Windows jest zainstalowany obok linuxa to pliki .efi Microsoftu będą na tej samej partycji co pliki .efi Linuxa. Jeżeli jest na komputerze zainstalowany sam windows to trzeba uruchomić na komputerze jakąś dystrybucję live i dokonać podpisu na wersji live.

Podpisywanie Windowsa wykonuje się przy pomocy narzędzia sbsign:

bootx64.efi:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/Boot/bootx64.efi --output /boot/efi/EFI/Boot/bootx64.efi

bootmgfw.efi:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi --output /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi

bootmgr.efi:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/Microsoft/Boot/bootmgr.efi --output /boot/efi/EFI/Microsoft/Boot/bootmgr.efi

memtest.efi:

sbsign --cert /root/SecureBoot/db.crt --key /root/SecureBoot/db.key /boot/efi/EFI/Microsoft/Boot/memtest.efi --output /boot/efi/EFI/Microsoft/Boot/memtest.efi

W miejsca przykładowych ścieżek /root/SecureBoot/db.crt i w /root/SecureBoot/db.key należy wstawić własne ścieżki do klucza publicznego i prywatnego.

Można uruchomić ponownie komputer i Windows na customowych kluczach w Secure Boot normalnie się uruchomił:

:warning: UWAGA!!! Przy aktualizacji systemu często Windows aktualizuje pliki .efi, co powoduje że prawie co każdą aktualizację wymagającą ponownego uruchomienia trzeba od nowa podpisywać pliki .efi Windowsa.

Sumy kontrolne w “db” zamiast podpisów cyfrowych

Secure Boot daje możliwość dodania do bazy db sumy kontrolnej danego pliku wykonywalnego, jest to alternatywa dla podpisywania pliku. Jest to dobre chociażby jak chcemy zezwolić na uruchamianie instalatora Windowsa czy innego systemu (chociażby live) z płyty (na której nie można dokonać zapisu). Pokażę to na przykładzie instalatora Windowsa.

Aby dodać sumę kontrolną do db należy wydać polecenie:

efi-updatevar -b <ścieżka do pliku wykonywalnego> -k <ścieżka do klucza prywatnego KEK> db

w przypadku instalatora Windowsa trzeba dodać sumę kontrolną jednego pliku znajdującego się w efi/microsoft/boot/cdboot.efi, po podmontowaniu płyty w /media/cdrom to ścieżka do cdboot.efi to będzie /media/cdrom/microsoft/boot/cdboot.efi

Czyli polecenie do dodania sumy kontrolnej instalatora systemu Windows będzie:

efi-updatevar -b /media/cdrom0/efi/microsoft/boot/cdboot.efi -k /root/SecureBoot/KEK.key db

Jeżeli podczas próby aktualizacji bazy db będzie komunikat Operation not permitted to należy wydać polecenie:

chattr -i /sys/firmware/efi/efivars/db-*

po wykonaniu tego polecenia i polecenia efi-readvar -v db można zauważyć że suma kontrolna znajduje się w bazie.

obraz_2021-07-18_022139

Po restarcie jest możliwość uruchomienia instalatora systemu Windows:

Baza sygnatur zabronionych

Do tej bazy dodaje się sumy kontrolne oprogramowania, które nie może być uruchomione czy odwołane certyfikaty cyfrowe. Do tej bazy dodaje się sumy kontrolne narzędziem efi-updatevar.

Składnia polecenia dodania sumy kontrolnej pliku wykonywalnego do bazy sygnatur zabronionych:

efi-updatevar -b <ścieżka do pliku wykonywalnego> -k <ścieżka do klucza prywatnego KEK> dbx

Przykładowo - z jakiś powodów chcemy zabronić możliwość uruchomienia podpisanego vmlinuz, wtedy należy wydać polecenie:

efi-updatevar -b /boot/vmlinuz-5.10.0-kali9-amd64 -k /root/SecureBoot/KEK.key dbx

Po restarcie komputera widać tego efekt - system nie może być załadowany, ponieważ suma kontrolna vmlinuz znajduje się w bazie sygnatur zabronionych.

Zakończenie

W zasadzie jest to wszystko co chciałem przekazać w tym poradniku na temat Secure Boot. Mam nadzieję że komuś się przyda ten poradnik i że w dosyć transparentny sposób objaśniłem działanie mechanizmu demonizowanego przez środowisko Open Source.

Poradnik miesiąca: lipiec 2021

6 polubień