Как Шим проверяет двоичные файлы в безопасной загрузке?

UEFI shim loader

shim - это тривиальное приложение EFI, которое при запуске пытается открыть и выполнить другое приложение. Сначала он попытается сделать это с помощью стандартных вызовов EFI LoadImage() и StartImage(). Если они терпят неудачу (потому что безопасная загрузка включена, а двоичный файл не подписан, например, с соответствующим ключом), он затем проверяет двоичный файл по встроенному сертификату. Если это удастся, и если двоичный файл или ключ подписи не внесены в черный список, то shim переместит и выполнит двоичный файл.

Я читал, чтобы понять, как происходит процедура проверки при включенной опции безопасной загрузки:

Разница между vmlinuz * -generic и * -generic.efi.signed

Как на самом деле работает Secure Boot?

Управление загрузчиками EFI для Linux: управление безопасной загрузкой

Теперь я могу сказать, что процедура выглядит следующим образом:

Шим сначала запускается прошивкой машины. Теперь шим должен запустить загрузчик. Что я не понимаю, так это то, как шим проверяет двоичные файлы? Например, в приведенном выше абзаце говорится, что shim пытается запустить другое приложение через стандартные вызовы EFI LoadImage() и StartImage(), и в случае неудачи shim пытается проверить двоичный файл из встроенного сертификата. Этот встроенный сертификат тогда принадлежит шиму? В сущности, именно поэтому шим называется диспетчером ключей владельца машины (MOK)? Потому что у него есть своя база данных ключей для проверки двоичных файлов.

Проще говоря, прошивка машины имеет собственную базу данных ключей в NVRAM для проверки двоичных файлов, а у shim есть собственная база данных ключей для проверки двоичных файлов?

После того, как загрузчик был проверен и выполнен, где загрузчик ищет ключи подписанного ядра, которые ему нужно загрузить, например, из базы данных микропрограммного обеспечения ключей?

3
задан 29 August 2017 в 21:20

2 ответа

Поскольку Вы правильно вывели, SHIM попытается загрузиться от LoadImage() и StartImage() сначала. EFI затем проверит это соответствия подписи (посредством использования внутреннего механизма SecureBoot). Если LoadImage() возвраты EFI_SECURITY_VIOLATION, система попытается к stage2 загрузки нейтрализации (в этом случае, GRUB2) из внутреннего сертификата.

Этот сертификат испекся в систему во время компиляции, которая была сделана Каноническим в этом случае. Этот сертификат может быть извлечен из использования КОНТЕЙНЕРА binwalk или подобная утилита.

Эффективно, это позволяет SecureBoot иметь проверенную подпись shim сохраненный в кэше, который затем в свою очередь разрешает shim проверить, что GRUB был подписан с вышеупомянутым сертификатом. Если это было, GRUB успешно загружается.

SHIM будет использовать системные ключи везде, где возможный - который является почему LoadImage() и StartImage() используются сначала. Только если это не работает, ШИММИРУЕТ попытку загрузить stage2 его собственным внутренним сертификатом. Вы видите этот код здесь (часть verify_buffer), который называют в части handle_image цепочка.

Вся цепочка проверки похожа на это:

  1. Проверьте системные хеши и список MOK
  2. Удостоверьтесь, что двоичный файл не помещен в черный список
  3. Попытайтесь проверить двоичный файл через белый список MOK/BIOS
  4. Проверьте по внутренним подписям, как определено ключом сборки и собственными внутренними ключами КОНТЕЙНЕРА.

Также важно, чтобы менеджер MOK не был самой базой данных MOK. Последний сохраняется встроенным микропрограммным обеспечением EFI, которое берет команды для того, что добавить/удалить от производителя во время высвечивания, а также операционной системы (или, в этом случае, shim). shim только хранит очень короткий список вышеупомянутых скомпилированных ключей для разрешения начальной загрузки - все остальное должно быть обработано встроенным микропрограммным обеспечением EFI.

5
ответ дан 30 August 2017 в 07:20

Ответ Kaz Wolfe довольно хорош, но я хочу подчеркнуть и подробно остановиться на нескольких точках....

последнее, которое я проверил, Контейнер в основном, обеспечило своего рода параллельную функцию проверки Защищенной загрузки. Это предназначается, чтобы использоваться GRUB, который разработан для запуска ядер Linux, которые не являются программами EFI. Таким образом Контейнер регистрирует себя в EFI способом, который позволяет последующим программам назвать Контейнер, чтобы проверить, что двоичные файлы подписываются. Контейнер делает так любым из двух способов:

  • встроенный ключ Контейнера - Большинство двоичных файлов Контейнера, включая тот, обеспеченный как часть Ubuntu, включает встроенный ключ Защищенной загрузки. Контейнер Ubuntu включает открытый ключ Canonical, который проверяет GRUB Ubuntu и ядро Linux. Этот ключ поэтому хранится в RAM и довольно временный, когда эти дела идут. Основной момент Контейнера должен позволить его последующей программе (GRUB) выполнить Защищенную загрузку проверка типа - но GRUB действительно не делает проверки Защищенной загрузки по сути, как описано вскоре. Без Контейнера, Канонического, должен был бы полагаться на Microsoft для подписания каждого нового выпуска GRUB и каждого нового ядра Linux, которое будет где-нибудь между непрактичным и невозможным.
  • владелец Машины Keys (MOKs) - MOKs являются в основном расширением встроенного ключа Контейнера, но они предназначаются, чтобы обычные пользователи управляли. Вы могли бы использовать MOKs, если Вы хотите запустить двоичные файлы, которые не подписываются с ключом Canonical. MOKs, как встроенные ключи Защищенной загрузки встроенного микропрограммного обеспечения, хранятся в NVRAM; но они более легко добавляются к NVRAM, с помощью программы под названием MokManager. Получение MOKs в NVRAM все еще достаточно утомительно, который большинство людей не беспокоит, и многие люди, у которых действительно есть проблемы с ним; но это легче, чем брать на себя полное управление Вашей подсистемы Защищенной загрузки, как описано на моей странице, на которую Вы сослались ( Руководящие Загрузчики EFI для Linux: Управление Защищенной загрузкой ).

В большинстве случаев, MOKs не используются; если Вы захотите к Windows двойной загрузки и Ubuntu, то Вы, вероятно, сделаете прекрасный со встроенными ключами встроенного микропрограммного обеспечения и ключом, встроенным в двоичный файл Контейнера Ubuntu. Вы использовали бы MOKs, если Вы хотите добавить другой дистрибутив Linux, скомпилируйте свои собственные ядра, используйте загрузчик кроме GRUB, используйте сторонние модули ядра, и т.д.

В дополнение к тем двум источникам, существуют также ключи Защищенной загрузки, встроенные во встроенное микропрограммное обеспечение. Я не вспоминаю, использует ли Контейнер те ключи. Это было бы неявно , используют их, если это использует EFI LoadImage() и StartImage() вызовы (который это делает, но я не рассмотрел контекст для этого ответа). Мое воспоминание - то, что его собственный код подтверждения не использует ключи Защищенной загрузки встроенного микропрограммного обеспечения, когда GRUB перезванивает, чтобы видеть, подписывается ли ядро, но я не мог бы помнить это правильно.

относительно того, как Контейнер интегрируется в систему Защищенной загрузки, последнее, которое я проверил, это не сделало. IIRC, для запуска его последующей программы (GRUB) Контейнер реализует свой собственный загружающий двоичный файл код, который напоминает упрощенную версию кода в демонстрационной реализации Tianocore UEFI. Этот код называет собственный код подтверждения Защищенной загрузки Контейнера, который проверяет двоичный файл по его встроенному ключу и локальному списку MOK, для запуска двоичного файла. (Это может также использовать собственные ключи Защищенной загрузки встроенного микропрограммного обеспечения, но я не положителен относительно этого.), После того как GRUB загружается, он вызывает функцию двоичной проверки Контейнера для проверки ядра Linux, которое GRUB запускает его собственным способом (не способ, которым EFI запускает программы EFI). Таким образом Контейнер действительно не интегрирует себя во встроенное микропрограммное обеспечение очень глубоко; это просто делает один или две из его функций доступный для последующих программ, уезжая LoadImage() и StartImage() функции EFI неизменный.

Тем не менее EFI действительно обеспечивает способы заменить или добавить нормальные системные вызовы EFI, и некоторые инструменты действительно используют эти методы. Например, программа PreLoader, которая была инструментом, чтобы сделать что-то подобное тому, что делает Контейнер, интегрировала себя более глубоко во встроенное микропрограммное обеспечение; это использовало системные вызовы EFI, разработанные для исправления поврежденных или устаревших функций для изменения StartImage() так, чтобы это проверило и обычные ключи Защищенной загрузки UEFI и MOK. PreLoader вполне прилично оказался нереален; его разработчики и разработчики Контейнера сотрудничали, чтобы сфокусироваться на Контейнере, а не PreLoader как стандартный инструмент Linux Secure Boot. AFAIK, Контейнер не принял PreLoader глубже интеграция UEFI; однако, это было некоторое время, так как я посмотрел на код очень тесно, таким образом, я могу устареть на этом. Это сказало....

Мой собственный диспетчер начальной загрузки перенаходки использует код, который я взял из программы PreLoader для "склеивания" двоичного кода подтверждения Контейнера в нормальную подсистему проверки UEFI. Таким образом, с перенаходкой в изображении, любая попытка запустить программу EFI с помощью LoadImage() и StartImage() вызовы код аутентификации Контейнера сначала и, если это перестало работать, называет стандартную аутентификацию Защищенной загрузки UEFI второй. gummiboot/systemd-boot диспетчер начальной загрузки делает что-то подобное. Обе программы делают это, потому что они запускают ядро Linux посредством его загрузчика тупика EFI, что означает, что они полагаются на EFI LoadImage() и StartImage() вызовы. Это контрастирует с GRUB, который является загрузчиком полной начальной загрузки, который запускает ядро Linux его собственным способом, таким образом, GRUB не нужны эти системные вызовы EFI для распознавания ключа Контейнера или локального списка MOK.

я надеюсь, что это помогает разъяснить вещи, но я не уверен, что это будет. Детали того, как вся эта работа довольно грязна, и это было некоторое время, так как я имел дело с ними во всех подробностях, таким образом, мои собственные мысли столь не организованы, как они могли бы быть.

0
ответ дан 30 August 2017 в 07:20

Другие вопросы по тегам:

Похожие вопросы: