Secure Boot в Linux: цепочка доверия от UEFI до загрузки ядра и модулей

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

Базы ключей в UEFI-прошивке​


Прошивка хранит несколько наборов ключей в энергонезависимой памяти (NVRAM):

  • PK (Platform Key) — корневой ключ платформы. Определяет, кто имеет право изменять остальные базы. Обычно принадлежит производителю оборудования.
  • KEK (Key Exchange Key) — ключи, уполномоченные обновлять базы данных подписей.
  • db (Signature Database) — список доверенных сертификатов и хешей. Бинарник, подписанный ключом из db, считается доверенным.
  • dbx (Forbidden Signature Database) — список отозванных сертификатов и хешей. Даже если подпись есть в db, наличие в dbx блокирует загрузку.

Большинство x86-систем поставляются с сертификатами Microsoft в db. Именно это позволяет Linux-дистрибутивам использовать модель shim: бинарник shim подписан ключом Microsoft, который уже доверен прошивке.

Переменные загрузки NVRAM​


Прошивка определяет, что загружать, через переменные NVRAM:

  • BootXXXX (например, Boot0000, Boot0001) — содержат путь к EFI-бинарнику и параметры.
  • BootOrder — задаёт приоритет записей BootXXXX.

При включении Secure Boot прошивка читает переменную BootOrder, находит первую активную запись и пытается загрузить указанный EFI-файл, предварительно проверив его подпись.

Shim: мост между Microsoft и дистрибутивом​


Shim — минимальный pre-bootloader, подписанный Microsoft. Прошивка валидирует его подпись по сертификату из db и передаёт управление.

Внутри shim встроена собственная база доверия, содержащая сертификат дистрибутива (например, Canonical для Ubuntu). Это позволяет shim проверять подписи GRUB, ядра и MokManager без необходимости добавлять сертификат каждого дистрибутива в прошивку.

После валидации shim загружает второй этап — либо GRUB (штатная загрузка), либо MokManager (управление ключами).

GRUB и загрузка ядра​


GRUB подписан ключом дистрибутива. Shim проверяет эту подпись и передаёт управление. GRUB читает конфигурацию с раздела /boot, находит образ ядра и initrd.

Ядро в режиме Secure Boot представляет собой самодостаточный EFI-бинарник, подписанный ключом дистрибутива. GRUB проверяет подпись ядра перед передачей управления. Если подпись невалидна — загрузка прерывается.

Важный нюанс: initrd не проверяется. Это известное ограничение цепочки доверия — содержимое initramfs остаётся за пределами криптографической верификации на этапе загрузки.

После загрузки ядро отключает Boot Services прошивки и переходит в пользовательский режим, где доступ к UEFI-переменным становится read-only.

Подпись модулей ядра​


Модули ядра обладают широкими привилегиями — фактически это код, работающий в ring 0. Поэтому механизм Secure Boot распространяется и на них.

Как устроена проверка​


Подсистема подписи модулей (module signing facility) использует X.509-сертификаты. Поддерживаются алгоритмы RSA, NIST P-384 ECDSA и NIST FIPS-204 ML-DSA. Хеш-алгоритмы для RSA и ECDSA: SHA-2 и SHA-3 с размерами 256, 384 и 512 бит.

Проверка выполняется целиком внутри ядра — userspace-компоненты не участвуют. Модули загружаются через insmod, modprobe, init_module() или finit_module() без дополнительной обработки на стороне пользователя.

Ключевые параметры конфигурации ядра​


ПараметрНазначение
CONFIG_MODULE_SIGВключает проверку подписей модулей
CONFIG_MODULE_SIG_FORCEЗапрещает загрузку неподписанных модулей и модулей с неизвестным ключом
CONFIG_MODULE_SIG_ALLАвтоматически подписывает модули на этапе modules_install
CONFIG_MODULE_SIG_KEYПуть к PEM-файлу с приватным ключом и сертификатом (по умолчанию certs/signing_key.pem)
CONFIG_SYSTEM_TRUSTED_KEYSPEM-файл с дополнительными сертификатами для системного keyring

Режимы enforcement​


При CONFIG_MODULE_SIG_FORCE=y (или параметре командной строки module.sig_enforce=1) ядро загружает только модули с валидной подписью, для которой у него есть публичный ключ. Попытка загрузить неподписанный модуль завершается ошибкой.

Если CONFIG_MODULE_SIG_FORCE выключен (permissive-режим), неподписанные модули загружаются, но ядро помечается как tainted, а модуль получает флаг E.

Модуль с некорректно сформированным блоком подписи отклоняется в любом режиме.

Встроенный keyring​


Публичные ключи для проверки подписей хранятся в keyring .builtin_trusted_keys. Просмотреть его содержимое можно через /proc/keys:

Код:
cat /proc/keys | grep builtin_trusted_keys

Дополнительные ключи можно добавить командой keyctl padd, но только если новый ключ подписан ключом, уже находящимся в .builtin_trusted_keys.

Архитектурный код может также импортировать публичные ключи из аппаратного хранилища — например, из базы ключей UEFI.

Machine Owner Keys (MOK)​


MOK — механизм, позволяющий пользователю добавлять собственные ключи доверия без модификации прошивки. Это основной способ подписывать сторонние модули (DKMS-драйверы, проприетарные модули NVIDIA и т. п.).

Генерация и регистрация​


При установке или обновлении системы, если требуются сторонние модули:

  1. Автоматически генерируется пара ключей MOK.
  2. Пользователю предлагается задать пароль (потребуется при следующей загрузке).
  3. Сторонние модули подписываются сгенерированным MOK.
  4. При перезагрузке MokManager выводит текстовый интерфейс с предложением зарегистрировать ключ.
  5. Пользователь выбирает «Enroll MOK», подтверждает отпечаток сертификата и вводит пароль.
  6. Ключ записывается в trust-базу shim, система перезагружается.

Пароль, заданный пользователем, действителен только для одного запуска shim и MokManager. После завершения или отмены процесса он очищается.

Ограничения MOK​


Начиная с shim 15.4, ключи MOK, помеченные OID 1.3.6.1.4.1.2312.16.1.2 (Module-signing only), принимаются ядром для проверки модулей, но игнорируются shim и GRUB при валидации загрузочных образов. Это означает, что MOK нельзя использовать для подписи собственного загрузчика или ядра — только для модулей.

Приватный ключ MOK хранится на файловой системе как обычный файл с правами root. Это осознанный компромисс: наличие root-доступа и так даёт полный контроль над системой, но администраторам стоит учитывать, что MOK на диске фактически стирает границу между root и kernel mode.

Подпись собственного модуля​


Для ручной подписи используется утилита scripts/sign-file из дерева исходников ядра. Она принимает четыре аргумента: хеш-алгоритм, путь к приватному ключу, путь к сертификату и путь к модулю.

Bash:
scripts/sign-file sha512 kernel-signkey.priv kernel-signkey.x509 module.ko

Если приватный ключ защищён паролем или PIN-кодом, его передают через переменную окружения KBUILD_SIGN_PIN.

Генерация пары ключей через OpenSSL:

Bash:
openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
  -config x509.genkey -outform PEM \
  -out kernel_key.pem -keyout kernel_key.pem

Полученный файл kernel_key.pem содержит и приватный ключ, и сертификат. Путь к нему указывают в CONFIG_MODULE_SIG_KEY.

Особенности подписанного модуля​


  • Подпись добавляется в конец файла. Маркер ~Module signature appended~. подтверждает наличие подписи, но не её валидность.
  • Подписанный модуль нельзя strip — подпись покрывает весь ELF-файл, включая отладочную информацию.
  • Хеш-алгоритм при подписи не обязан совпадать с настроенным в ядре, но должен быть либо встроен в ядро, либо загружаться без зависимостей.

Что происходит при сбое валидации​


ЭтапПоведение при невалидной подписи
Прошивка → shimЗагрузка не начинается, firmware выводит ошибку
shim → GRUBshim останавливает процесс
GRUB → ядроGRUB отказывается передавать управление
Ядро → модульinsmod/modprobe возвращает ошибку, модуль не загружается

На любом этапе цепочки неподписанный или некорректно подписанный бинарник блокируется.

Отключение Secure Boot и обходные пути​


Если необходимо загрузить неподписанное ядро или модуль без собственной подписи:

  • sudo mokutil --disable-validation — отключает проверку на уровне shim (требуется пароль и перезагрузка). Secure Boot в прошивке остаётся включённым, но shim перестаёт валидировать образы.
  • Отключение Secure Boot в настройках UEFI — полностью убирает проверку подписей на уровне прошивки.
  • Подпись собственного ядра или загрузчика ключом, зарегистрированным через MokManager (без OID module-signing-only).

Практическая проверка состояния Secure Boot​


Утилита mokutil предоставляет интерфейс для взаимодействия с MOK и проверки состояния Secure Boot на уровне shim. В частности, она позволяет отключить валидацию (--disable-validation) и управлять регистрацией ключей.

Для диагностики проблем с загрузкой модулей полезно обращаться к dmesg: при попытке загрузить неподписанный модуль в enforce-режиме ядро выводит сообщение об ошибке с указанием имени модуля. В permissive-режиме модуль загрузится, но в выводе dmesg и в /proc/sys/kernel/tainted появится отметка о tainted-состоянии с символом E.

Проверить, какие ключи находятся в системном keyring, можно через /proc/keys — там отображаются все асимметричные ключи, включая сертификат дистрибутива и зарегистрированные MOK.

Для систем, где Secure Boot управляется через UEFI-прошивку, состояние можно также проверить через EFI-переменные, доступные в /sys/firmware/efi/efivars/. Если каталог существует и содержит переменную SecureBoot, система загружена в UEFI-режиме.

Эволюция Secure Boot в Ubuntu​


Поддержка Secure Boot в Ubuntu развивалась поэтапно:

  • Ubuntu 12.04 LTS — первое появление Secure Boot: enforcing для загрузчика, non-enforcing для ядра.
  • Ubuntu 18.04 LTS — полная верификация: загрузчик, ядро и модули.
  • Ubuntu 20.04 LTS — добавлена поддержка grub-efi-arm64-signed для ARM64.
  • Ubuntu 21.04 — shim 15.4 с ограничением MOK-ключей только для подписи модулей.

Пакеты shim-signed и grub-efi-amd64-signed (или grub-efi-arm64-signed) содержат подписанные бинарники, распространяемые через основной архив Ubuntu.

Автоматическая подпись DKMS-модулей​


Если в системе уже существует зарегистрированный MOK, установка нового DKMS-модуля (стороннего драйвера) автоматически подписывает собранный модуль этим ключом. Взаимодействие с пользователем не требуется.

Если MOK отсутствует или не зарегистрирован, система автоматически создаёт новый ключ непосредственно перед подписью и предлагает пользователю зарегистрировать его при следующей перезагрузке через MokManager.

При обновлении системы пакеты shim и shim-signed обновляются, генерируется новый MOK, сторонние модули пересобираются под новое ядро и подписываются. После перезагрузки MokManager предлагает зарегистрировать обновлённый ключ и, при необходимости, повторно включить валидацию shim.

Источники​


 
Назад
Верх Низ