Разбираемся в процессе Secure Boot в Linux

Разбираемся в процессе Secure Boot в Linux


Эта заметка начнётся с общего обзора процесса загрузки Ubuntu, а затем углубится в то, какую роль в нём играет SecureBoot, если он включён. Я затрону такие вещи, как shim, переменные EFI и MOK. Информация, которую вы тут увидите, собрана из источников, перечисленных в конце статьи. Также будут команды и примеры вывода, чтобы картина получилась более целостной.

Понимание процесса загрузки вместе с SecureBoot важно, потому что без нормального представления о том, как всё устроено внутри Linux-системы, очень легко случайно превратить её в кирпич, пытаясь включить такие настройки, как SecureBoot. Это низкоуровневые операции, которые при неосторожности могут наделать много бед.

Типичный процесс загрузки

Когда Ubuntu загружается, она проходит через четыре основные фазы.

  1. Фаза BIOS — прошивка на материнской плате, обычно хранящаяся в виде ПЗУ, инициализирует аппаратные компоненты и получает код для загрузчика.
  2. Фаза загрузчика — загрузчик поднимает операционную систему в память вместе с начальным образом файловой системы initrd.
  3. Фаза ядра — ядро запускает скрипт init внутри файловой системы initrd. Он загружает драйверы и монтирует корневой раздел.
  4. Запуск системы — операционная система поднимает демоны и сервисы, настраивает сеть, монтирует файловые системы, запускает системный логгер и делает прочую инициализацию.

Обычно на Linux-системах есть 512-битный раздел под названием Master Boot Record (MBR). В нём хранится загрузчик (GRUB, LILO, yaboot и другие) и загрузочные записи. Это одно из мест, откуда Linux может стартовать. Другие варианты — загрузчик на носителе вроде USB-флешки или CD-R, либо загрузчик, который приходит по сети, например через Preboot Execution Environment (PXE).

Secure Boot

Secure Boot — это стандарт безопасности. Когда компьютер включается, процесс Secure Boot стартует с прошивки на материнской плате, которая проверяет криптографические подписи каждого файла, участвующего в загрузке. Сюда входят драйверы прошивки UEFI (они же optional ROMs), EFI-приложения и сама операционная система. Если всё проверяется успешно, машина продолжает загрузку, и прошивка передаёт управление операционной системе.

Shim

При включении Secure Boot важно понимать, что такое shim. В контексте Secure Boot это пред-загрузчик, который умеет работать с прошивкой, enforcing Secure Boot. Он позволяет загружать и выполнять загрузчики и модули ядра, даже если их нет в базе доверенных ключей Secure Boot. В Ubuntu shim ставится заранее и подписан сертификатным центром Microsoft.

Secure Boot использует асимметричную криптографию, то есть пару ключей — публичный и приватный. Пользователь может создать свою пару: приватным ключом подписываются все программы, которым разрешено выполняться, включая загрузчик GRUB. Прошивка BIOS или UEFI потом использует публичный ключ, чтобы проверять контрольные суммы и подписи перед запуском этих программ.

Вы можете проверить подпись своего shim-загрузчика с помощью sbverify, который входит в пакет sbsigntool:

# locate your shim binary
$ SHIM=$(sudo find /boot/efi/EFI/ -iname "shim*" 2>/dev/null)
$ sbverify $SHIM
Signature verification OK

Переменные UEFI

Ещё одна важная вещь — переменные UEFI, которые хранятся в энергонезависимой памяти прошивки (NV-RAM). В них записаны разные данные: порядок загрузки, тайм-ауты, сетевые настройки, информация о накопителях и параметры Secure Boot. Для каждой переменной есть свой бинарный файл в каталоге /sys/firmware/efi/efivars/. Формат имён такой: имя переменной плюс GUID вендора. Например, файл

SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c

может хранить значение, включён Secure Boot (0x01) или выключен (0x00).

Посмотреть эти переменные можно, просто перечислив содержимое /sys/firmware/efi/efivars/ или через инструмент efivarfs, чтобы вывести список и прочитать значения:

$ sudo apt-get install efivar
$ sudo efivar -p -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot

В этом примере значение переменной SecureBoot — 0x01, то есть Secure Boot включён. Есть ещё несколько ключевых переменных, связанных именно с Secure Boot:

8be4df61-93ca-11d2-aa0d-00e098032b8c-PKDefault
8be4df61-93ca-11d2-aa0d-00e098032b8c-KEKDefault
8be4df61-93ca-11d2-aa0d-00e098032b8c-dbDefault
8be4df61-93ca-11d2-aa0d-00e098032b8c-dbxDefault

Эти переменные относятся к базам ключей, которые определяют, можно ли считать модуль безопасным для загрузки.

Базы данных Secure Boot

Secure Boot опирается на четыре ключевые базы. Их можно подробно изучить в официальной спецификации, но кратко смысл такой:

  • Allowed Signature Database (db) — список криптографических подписей, которые разрешено загружать во время старта системы.
  • Disallowed Signature Database (dbx) — список подписей, которые, наоборот, запрещены к загрузке.
  • Key Enrollment Key Database (KEK) — набор ключей, которые используются для проверки подлинности других баз.
  • Platform Key Database (PK) — содержит публичный ключ, с помощью которого проверяются подписи загрузчиков или прошивки, если они подписаны соответствующим приватным ключом. Рекомендуемый формат платформенного ключа для UEFI — RSA-2048.

Эти базы фактически задают правила: какие подписи считаются допустимыми, а какие нет. Для Secure Boot это критично, потому что именно так обеспечивается проверка целостности модулей перед их выполнением.

Machine Owner Keys (MOK)

Ещё один элемент загрузочного процесса — Machine Owner Keys (MOK). Это дополнительная база ключей, которой может управлять сам пользователь. Она не связана с тем сертификатным ключом, который поставляется вместе с shim. MOK дают пользователю больше контроля над тем, какие модули можно загружать. Например, когда пользователь регистрирует MOK в системе, связанный с ним ключ добавляется в базу разрешённых подписей (db). Это значит, что любой бинарник, подписанный этим ключом, будет считаться доверенным прошивкой во время загрузки.

Обычно MOK-файлы находятся в каталоге /var/lib/shim-signed/mok/ и называются MOK.der, MOK.pem или MOK.priv. Если у вас ещё нет MOK-ключей, а создать их нужно, можно воспользоваться такими командами:

# mkdir -p /var/lib/shim-signed/mok/
# cd /var/lib/shim-signed/mok/
# openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -days 36500 -subj "/CN=My Name/"
# openssl x509 -inform der -in MOK.der -out MOK.pem

По умолчанию shim предоставляет утилиту управления MOK под названием MokManager. Она позволяет «добавлять ключи, удалять доверенные ключи, регистрировать хэши бинарников и переключать проверку Secure Boot на уровне shim», как описано в документации Ubuntu. Учтите, что для работы с MokManager обычно требуется пароль — чтобы аутентифицировать пользователя, который вносит изменения.

MokManager помогает корректно настроить ключи, если требуется управление ими. После завершения настройки система перезагрузится, чтобы применить изменения. Если всё прошло как надо, загрузка продолжится в обычном режиме, без появления экрана MokManager.

Конфигурация загрузчика и полезная информация

Можно покопаться глубже в том, как ваша Linux-машина загружается. Один из способов — посмотреть файл /proc/cmdline. В нём лежат параметры командной строки ядра, которые были переданы ему во время загрузки.

$ cat /proc/cmdline
# example output
BOOT_IMAGE=/boot/vmlinuz-5.11.0-16-generic root=UUID=12345678-1234-1234-1234-1234567890AB ro quiet splash

Эта команда показывает путь к файлу образа ядра, который загрузчик передал ядру через BOOT_IMAGE. Опция quiet splash в конце — стандартная штука для GRUB: она отключает подробные сообщения во время старта и выводит графический сплэш-скрин.

Ядро — это бинарник, содержащий основной код ОС. В нём всё необходимое, чтобы загрузиться, управлять памятью, работать с устройствами ввода-вывода и запускать пользовательские программы. Загрузчик использует его, чтобы стартовать систему. Имя файла ядра обычно подсвечивает его версию и архитектуру. Например, ядро vmlinuz-5.4.0-1042-aws — это версия 5.4.0-1042 для AWS-окружения.

Загрузчик использует свои драйверы файловых систем из initramfs, и вы можете посмотреть их содержимое, если знаете, какой файл /boot/initrd* соответствует текущему ядру. Проще всего — воспользоваться утилитами из initramfs-tools-core:

## list files inside the initramfs
$ lsinitramfs /boot/initrd.img-$(uname -r)
.
kernel
kernel/x86
.
bin
conf
conf/arch.conf
conf/conf.d
conf/conf.d/resume
-- snip --

## extract files from the initramfs
$ unmkinitramfs /boot/initrd.img-$(uname -r) initramfs/

Это позволяет пройтись по файловой системе initramfs и лучше понять, что происходит во время ранних этапов загрузки. Если вы распакуете initramfs, то увидите внутри каталога ./initramfs три папки: early, early2 и main:

$ ls initramfs
early  early2  main

В контексте initramfs early и early2 — это первая и вторая стадии начальной RAM-файловой системы. На первой стадии загружается минимальный набор драйверов и утилит, необходимых для инициализации оборудования и монтирования настоящего корневого раздела. На второй стадии (early2) подгружаются дополнительные драйверы и инструменты, которые нужны для полной инициализации системы.

Папка main внутри initramfs содержит собственно образ корневой файловой системы, а также дополнительные инструменты и драйверы, которые могут понадобиться во время загрузки. После монтирования корневой ФС система продолжает запуск обычных сервисов и демонов, необходимых для работы операционной системы.

Проверка подписей вручную

Можно проверить, какие модули ядра подписаны, с помощью команды modinfo. Подпись ядра в выводе выглядит как длинная строка шестнадцатеричных значений, разделённых двоеточиями.

$ modinfo example.ko
filename:       /lib/modules/5.10.0-5-amd64/kernel/drivers/misc/example.ko
version:        1.0.0
license:        GPL
description:    Example kernel module
author:         John Doe <jdoe@example.com>
srcversion:     12AB34CD5678EF90ABCD1234
sig_key:        A0:3B:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF
sig_hashalgo:   sha256
signature:      12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF

Заключение

Спасибо, что дочитали этот обзор Secure Boot. Очень советую заглянуть в источники ниже — эта заметка лишь поверхностно прошлась по теме. Надеюсь, она помогла вам лучше почувствовать, насколько сложной и одновременно изящной является система, когда Linux-машина включается и оживает.

Источники


Report Page