- PVSM.RU - https://www.pvsm.ru -

Укрощаем UEFI SecureBoot

Укрощаем UEFI SecureBoot - 1 Данные обещания надо выполнять, тем более, если они сделаны сначала в заключительной части опуса о безопасности UEFI [1], а потом повторены со сцены ZeroNights 2015 [2], поэтому сегодня поговорим о том, как заставить UEFI SecureBoot работать не на благо Microsoft, как это чаще всего настроено по умолчанию, а на благо нас с вами.
Если вам интересно, как сгенерировать свои обственные ключи для SecureBoot, как установить их вместо стандартных (или вместе с ними), как подписать ваш любимый EFI-загрузчик, как запретить загрузку неподписанного или подписанного чужими ключами кода, как выглядит интерфейс для настройки SecureBoot у AMI, Insyde и Phoenix и почему это, по большому счету, совершенно не важно — добро пожаловать под кат, но опасайтесь большого количества картинок и длинных консольных команд.

Введение

О том, как устроен и работает SecureBoot, я уже рассказывал в начале пятой части вышеупомянутого опуса [3], повторяться смысла не вижу. Если вы не в курсе, о чем весь этот UEFI SecureBoot вообще, кто такие PK, KEK, db и dbx, и почему с точки зрения SecureBoot по умолчанию хозяином вашей системы является производитель UEFI, а единственным авторизованным пользователем является Microsoft — смело проследуйте туда, мы вас тут пока подождем.

С ликбезом закончили, теперь к делу. Несмотря на то, что про создание своих ключей и настройку SecureBoot написано за три последних года с десяток отличных статей (ссылки на часть из которых приведены в разделе Литература), воз и ныне там. Основная проблема с информацией о настройке SecureBoot даже в англоязычном сегменте сети (не говоря уже о рунете) — большая часть статей, текстов и постов обрывается на «вот у нас теперь есть ключи в формате EFI Signature List, добавьте их зависимым от вашего вендора прошивки способом и готово». При этом сами вендоры не торопятся описывать меню настройки SecureBoot ни в документации на свои платформы для OEM'ов, ни в мануалах на конечные системы, в результате пользователь теряется на незнакомой местности и либо отключает SecureBoot, мешающий загружать его любимую OpenBSD (или что там у него), либо оставляет его на настройках по умолчанию (а чего, Windows грузится же). Именно этот последний шаг я и попытаюсь описать более подробно, но не в ущерб остальным необходимым шагам.

Тестовая конфигурация

Специально для этой статьи я достал из закромов пару не самых новых ноутбуков с прошивками на платформах Phoenix SCT и Insyde H2O, а также совершенно новую плату congatec (разработкой прошивки для которой я занят в данный момент) на платформе AMI AptioV. Встречайте, наши тестовые стенды:
Укрощаем UEFI SecureBoot - 2
1. AMI, они же "треугольные": congatec conga-TR3 [4] @ conga-TEVAL [5], AMD RX-216GD (Merlin Falcon), AMI AptioV (UEFI 2.4)
Укрощаем UEFI SecureBoot - 3
2. Insyde, они же "квадратные": Acer Aspire R14 R3-471T [6] (Quanta ZQX), Intel Core i3-4030U (Ivy Bridge), Insyde H2O (UEFI 2.3.1C)
Укрощаем UEFI SecureBoot - 4
3. Phoenix, они же "полукруглые": Dell Vostro 3360 [7] (Quanta V07), Intel Core i7-3537U (Ivy Bridge), Phoenix SCT (UEFI 2.3.1C)

Об интерфейсах для настройки SecureBoot

На всех вышеперечисленных системах производитель заявляет о поддержке технологии UEFI SecureBoot, но интерфейс для ее настройки сильно отличается между системами. К счастью, это не очень большая проблема, поскольку для настройки SecureBoot на совместимых со спецификацией UEFI 2.3.1C (и более новых) прошивках никакого интерфейса в Setup, кроме возможности удаления текущего PK (т.е. перевода SecureBoot в так называемый Setup Mode) не требуется, а после этого можно использовать любое EFI-приложение, способное вызвать UEFI-сервис gRS->SetVariable с предоставленными пользователем данными, в том числе утилиту KeyTool.efi из пакета efitools [8], которая специально для управления ключами и предназначена, осталось только научиться ей пользоваться.
Тем не менее, если удобный интерфейс для настройки присутствует (у AMI он, на мой взгляд, даже удобнее KeyTool'а) — можно воспользоваться им, так что рассказывать про эти самые интерфейсы все равно придется.

Пара слов про скриншоты UEFI

Благодаря универсальности GOP, ConIn/ConOut и DevicePath можно было сесть и написать за полчаса простой DXE-драйвер, который снимал бы замечательные скриншоты в формате BMP со всего, что происходит в графической консоли после его (драйвера) загрузки по нажанию горячей клавиши, после чего сохранял бы их на первом попавшемся USB-носителе с ФС FAT32… Но его нужно сначала написать, потом отладить, потом интегрировать в прошивки так, чтобы они от этого не развалились (а на ноутбуках придется микросхему с прошивкой выпаивать и под программатор класть, если вдруг что-то не так пойдет), плюс с подконтрольного мне AptioV можно снимать скриншоты просто используя терминал и console serial redirection, а у остальных там настроек буквально на два-три экрана, которые можно банально с монитора сфотографировать, поэтому прошу вас, уважаемые читатели, простить вашего покорного слугу за эти кривые фотографии и за тот факт, что он — ленивая жопа.

Готовим плацдарм

Начнем с лирического отступления о наличии нужного софта для разных ОС. Несмотря на то, что Microsoft является одним из разработчиков технологии, в открытом доступе до сих пор отсутствуют нормальные средства для работы с ней из Windows (ключи можно сгенерировать утилитой MakeCert [9] из Windows SDK, а для всего остального предлагается использовать HSM [10] третьих лиц за большие деньги). Я подумывал сначала взять и написать нужную утилиту на Qt, но потому решил, что ключи и подписи каждый день генерировать не нужно, а на пару раз хватит и существующих решений. Можете попробовать переубедить меня в комментариях, если хотите.
В общем, для всего нижеперечисленного вам понадобится Linux (который можно запустить с LiveUSB, если он у вас не установлен). Для него существует целых два набора утилит для работы с SecureBoot: efitools/sbsigntool и EFIKeyGen/pesign. У меня есть положительный опыт работы с первым набором, поэтому речь пойдет именно о нем.
В итоге, кроме Linux, нам понадобятся несколько вещей:
1. Пакет openssl и одноименная утилита из него для генерирования ключевых пар и преобразования сертификатов из DER в PEM.
2. Пакет efitools, а точнее утилиты cert-to-efi-sig-list, sign-efi-sig-list для преобразования сертификатов в формат ESL и подписи файлов в этом формате, и KeyTool.efi для управления ключами системы, находящейся в SetupMode.
3. Пакет sbsigntool, а точнее утилита sbsign для подписи исполняемых файлов UEFI (т.е. загрузчиков, DXE-драйверов, OptionROM'ов и приложений для UEFI Shell) вашим ключом.
Загрузите Linux, установите вышеуказанные пакеты, откройте терминал в домашней директории и переходите к следующему шагу.

Генерируем собственные ключи для SecureBoot

Как обычно, есть несколько способов сделать что-либо, и чем мощнее используемый инструмент, тем таких способов больше. OpenSSL же как инструмент развит настолько, что кажется, что он умеет делать вообще всё, а если почитать к нему man — то и абсолютно всё остальное. Поэтому в этой статье я ограничусь непосредственной генерацией ключевых файлов, а танцы вокруг создания собственного самостоятельное изучение [11].

Генерируем ключевые пары

Ключей понадобится сгенерировать три штуки: PK, KEK и ISK.
Начнем с PK, для генерации которого нужно выполнить следующее

openssl req -new -x509 -newkey rsa:2048 -sha256 -days 365 -subj "/CN=Platform Key" -keyout PK.key -out PK.pem

после чего ввести и подтвердить пароль, который потом спросят при попытке подписи чего-либо получившимся закрытым ключом.
Командой выше мы просим OpenSSL сгенерировать нам ключевую пару RSA2048/SHA256 со сроком действия на один год, под названием Platform Key, с выводом закрытого ключа в файл PK.key, а открытого — в файл PK.pem. Если добавить -nodes, то для подписи этой ключевой парой не нужен будет пароль, но здесь мы этого делать не станем — с паролем хоть ненамного, но безопаснее.
Таким же образом генерируем ключевые пары для KEK и ISK, пароли при этом советую вводить разные:

openssl req -new -x509 -newkey rsa:2048 -sha256 -days 365 -subj "/CN=Key Exchange Key" -keyout KEK.key -out KEK.pem
openssl req -new -x509 -newkey rsa:2048 -sha256 -days 365 -subj "/CN=Image Signing Key" -keyout ISK.key -out ISK.pem

Конвертируем открытые ключи в формат ESL

Теперь нужно сконвертировать открытые ключи из формата PEM в понятный UEFI SecureBoot формат ESL. Этот бинарный формат описан в спецификации UEFI [12] (раздел 30.4.1 в текущей версии 2.5) и интересен тем, что файлы в нем можно соединять друг с другом конкатенацией, и этот факт нам еще пригодится.

cert-to-efi-sig-list -g "$(uuidgen)" PK.pem PK.esl
cert-to-efi-sig-list -g "$(uuidgen)" KEK.pem KEK.esl
cert-to-efi-sig-list -g "$(uuidgen)" ISK.pem ISK.esl

Ключ -g добавляет к сгенерированному ESL-файлу GUID, в нашем случае — случайный, полученый запуском утилиты uuidgen и использованием ее вывода. Если этой утилиты у вас нет — придумывайте GUIDы сами или оставьте значение по умолчанию.

Подписываем ESL-файлы

Для правильно работы SecureBoot необходимо, чтобы PK был подписан сам собой, KEK подписан PK, а хранилища db и dbx — сответственно KEK. При этом PK не может быть несколько, а вот ситуация с несколькими KEK хоть и встречается в дикой природе, но я все же настоятельно рекомендую удалить предустановленный ключ Microsoft из KEK по простой причине — db и dbx могут быть подписаны любым ключом из хранилища KEK, т.е. если ключ MS оттуда не удалить, то у MS будет возможность управлять содержимым db и dbx, т.е. добавлять любые новые ключи или хеши в список доверенной загрузки и удалять из него существующие. На мой взгляд, это немного слишком, и если мы берем управление ключами в свои руки, то нужно делать это до конца.

Если вы думаете иначе

Ну тогда вам прямая дорога вот сюда [10], там в самом конце раздела 1.3.4.3 есть ссылка [13] на сертификат Microsoft Corporation KEK CA 2011 в формате DER, из которого нужно сначала получить PEM командой

openssl x509 -in MicCorKEKCA2011_2011-06-24.crt -inform DER -out MsKEK.pem -outform PEM

затем сконвертировать полученный PEM в ESL командой

cert-to-efi-sig-list -g "$(uuidgen)" MsKEK.pem MsKEK.esl

после чего добавить получившийся файл к нашему файлу KEK.esl командой

cat KEK.esl MsKEK.esl > KEK.esl

Теперь Microsoft такой же авторизованный пользователь вашей платформы, как и вы сами, с чем я вас и поздравляю.

С другой стороны, если вы не хотите терять возможность загрузки Windows и подписанных ключом Microsoft исполняемых компонентов (к примеру, GOP-драйверов внешних видеокарт и PXE-драйверов внешних сетевых карточек), то к нашему ISK.esl надо будет добавить еще пару ключей — ключ Microsoft Windows Production CA 2011 [14], которым MS подписывает собственные загрузчики и ключ Microsoft UEFI driver signing CA [15], которым подписываются компоненты третьих сторон (именно им, кстати, подписан загрузчик Shim, с помощью которого теперь стартуют разные дистрибутивы Linux, поддерживающие SecureBoot из коробки).
Последовательность та же, что и под спойлером выше. Конвертируем из DER в PEM, затем из PEM в ESL, затем добавляем к db.esl, который в конце концов надо будет подписать любым ключом из KEK:

openssl x509 -in MicWinProPCA2011_2011-10-19.crt -inform DER -out MsWin.pem -outform PEM
openssl x509 -in MicCorUEFCA2011_2011-06-27.crt -inform DER -out UEFI.pem -outform PEM
cert-to-efi-sig-list -g "$(uuidgen)" MsWin.pem MsWin.esl
cert-to-efi-sig-list -g "$(uuidgen)" UEFI.pem UEFI.esl
cat ISK.esl MsWin.esl UEFI.esl > db.esl

Теперь подписываем PK самим собой:

sign-efi-sig-list -k PK.key -c PK.pem PK PK.esl PK.auth

Подписываем KEK.esl ключом PK:

sign-efi-sig-list -k PK.key -c PK.pem KEK KEK.esl KEK.auth

Подписываем db.esl ключом KEK:

sign-efi-sig-list -k KEK.key -c KEK.pem db db.esl db.auth

Если еще не надоело, можно добавить чего-нибудь еще в db или создать хранилище dbx, нужные команды вы теперь знаете, все дальнейшее — на ваше усмотрение.

Подписываем загрузчик

Осталось подписать какой-нибудь исполняемый файл ключом ISK, чтобы проверить работу SecureBoot после добавления ваших ключей. Для тестов я советую подписать утилиту RU.efi [16], она графическая и яркая, и даже издалека видно, запустилась она или нет. На самом деле, утилита эта чрезвычайно мощная и ей можно натворить добрых и не очень немало дел, поэтому после тестов лучше всего будет её удалить, и в дальнейшем подписывать только загрузчики.
В любом случае, подписываются исполняемые файлы вот такой командой:

sbsign --key ISK.key --cert ISK.pem --output bootx64.efi RU.efi

Здесь я заодно переименовал исполняемый файл в bootx64.efi, который нужно положить в директорию /EFI/BOOT тестового USB-носителя с ФС FAT32. Для 32-битных UEFI (избавь вас рандом от работы с ними) используйте bootia32.efi и RU32.efi.

В результате вот этого всего у вас получились три файла .auth, которые нужно будет записать «как есть» в NVRAM-переменные db, KEK и PK, причем именно в таком порядке. Скопируйте все три файла в корень другого USB-носителя с ФС FAT32, на котором в качестве /EFI/BOOT/bootx64.efi выступит /use/share/efitools/efi/KeyTool.efi (скопируйте его еще и в корень, на всякий случай) и ваш «набор укротителя SecureBoot» готов.

Укрощение строптивого

Начинается все одинаково: вставляем нашу флешку с ключами и KeyTool'ом в свободный USB-порт, включием машину, заходим в BIOS Setup.
Здесь, прежде чем заниматься настройкой SecureBoot, нужно отключить CSM, а с ним — и легаси-загрузку, с которыми наша технология не совместима. Также обязательно поставьте на вход в BIOS Setup пароль подлиннее, иначе можно будет обойти SecureBoot просто отключив его, для чего на некоторых системах с IPMI и/или AMT даже физическое присутсвие не потребуется.

AMI AptioV

У большинства прошивок, основанных на коде AMI, управление технологией SecureBoot находится на вкладке Security, у меня это управление выглядит так:
Укрощаем UEFI SecureBoot - 5
Заходим в меню Key Management (раньше оно было на той же вкладке, сейчас его выделили в отдельное) и видим там следующее:
Укрощаем UEFI SecureBoot - 6
Выбираем нужную нам переменную, после чего сначала предлагают выбрать между установкой нового ключа и добавлением к уже имеющимся, выбираем первое:
Укрощаем UEFI SecureBoot - 7
Теперь предлагается либо установить значение по умолчанию, либо загрузить собственное из файла, выбираем последнее:
Укрощаем UEFI SecureBoot - 8
Далее нужно устройство и файл на нем, а затем выбрать формат этого файла, в нашем случае это Authenticated Variable:
Укрощаем UEFI SecureBoot - 9
Затем нужно подтвердить обновление файла, и если все до этого шло хорошо, в результате получим лаконичное сообщение:
Укрощаем UEFI SecureBoot - 10
Повторяем то же самое для KEK и PK, и получам на выходе вот такое состояние:
Укрощаем UEFI SecureBoot - 11
Все верно, у нас есть единственный PK, всего один ключ в KEK и три ключа в db, возвращаемся в предыдущее меню кнопкой Esc и включаем SecureBoot:
Укрощаем UEFI SecureBoot - 12
Готово, сохраняем настройки и выходим с перезагрузкой, после чего пытаемся загрузиться с нашей флешки и видим вот такую картину:
Укрощаем UEFI SecureBoot - 13
Отлично, неподписанные загрузчики идут лесом, осталось проверить подписанный. Вставляем другую флешку, перезагружаемся и видим что-то такое:
Укрощаем UEFI SecureBoot - 14
Вот теперь можно сказать, что SecureBoot работает как надо.
Если у вашего AMI UEFI такого интерфейса для добавления ключей нет, то вам подойдет другой способ, о котором далее.

Insyde H2O

Здесь все несколько хуже, чем в предыдущем случае. Никакого интерфейса для добавления собственных ключей нет, и возможностей настройки SecureBoot предлагается всего три: либо удалить все переменные разом, переведя SecureBoot в Setup Mode, либо выбрать исполняемый файл, хеш которого будет добавлен в db, и его можно будет запускать даже в том случае, если он не подписан вообще, либо вернуться к стандартным ключам, в качестве которых на этой машине выступают PK от Acer, по ключу от Acer и MS в KEK и куча всякого от Acer и MS в db.
Впрочем, нет интерфейса — ну и черт с ним, у нас для этого KeyTool есть, главное, что в Setup Mode перейти можно. Интересно, что BIOS Setup не дает включить SecureBoot, если пароль Supervisor Password не установлен, поэтому устанавливаем сначала его, затем выполняем стирание ключей:
Укрощаем UEFI SecureBoot - 15
После чего на соседней вкладке Boot выбираем режим загрузки UEFI и включаем SecureBoot:
Укрощаем UEFI SecureBoot - 16
Т.к. фотографии у меня посреди ночи получаются невыносимо отвратительными, то скриншоты KeyTool'а я сделаю на предыдущей системе, и придется вам поверить в то, что на этой все выглядит точно также (мамой клянусь!).
Загружаемся с нашего носителя в KeyTool, и видим примерно следующее:
Укрощаем UEFI SecureBoot - 17
Выбираем Edit Keys, попадаем в меню выбора хранилища:
Укрощаем UEFI SecureBoot - 18
Там сначала выбираем db, затем Replace Keys, затем наше USB-устройство, а затем и файл:
Укрощаем UEFI SecureBoot - 19
Нажимаем Enter и без всяких сообщений об успехе нам снова показывают меню выбора хранилища. Повторяем то же самое сначала для KEK, а затем и для PK, после выходим в главное меню двойным нажатием на Esc. Выключаем машину, включаем заново, пытаемся загрузить KeyTool снова и видим такую картину (которую я утащил из дампа прошивки, ее фото на глянцевом экране еще кошмарнее, чем предыдущие):
Укрощаем UEFI SecureBoot - 20
Ну вот, одна часть SecureBoot'а работает, другая проверяется запуском подписанного нами RU.efi и тоже работает. У меня на этой системе Windows 8 установлена в UEFI-режиме, так вот — работает и она, Microsoft с сертификатом не подвели.

Phoenix SCT

Здесь возможностей еще меньше, и во всем меню Secure Boot Configuration на вкладке Security всего два пункта: возврат к стандартным ключам и удаление всех ключей с переводом системы в SetupMode, нам нужно как раз второе:
Укрощаем UEFI SecureBoot - 21
Затем на вкладке Boot нужно выбрать тип загрузки UEFI, включить SecureBoot, и создать загрузочную запись для KeyTool'а, иначе на этой платформе его запустить не получится:
Укрощаем UEFI SecureBoot - 22
Нажимаем Yes, выходим с сохранением изменений, перезагружаемся, нажимаем при загрузке F12, чтобы попасть в загрузочное меню, оттуда выбираем KeyTool, работа с которым описана выше. После добавления ключей и перезагрузки попытка повторного запуска KeyTool'а заканчивается вот так:
Укрощаем UEFI SecureBoot - 23
При этом установленный на той же машине Linux продолжает исправно загружаться, как и подписанная нами RU.efi, так что SecureBoot можно признать работоспособным.

Заключение

В итоге, благодаря утилитам с открытым кодом, удалось завести SecureBoot на системах с UEFI трех различных вендоров, сгенерировать свои собственные ключи и подписать ими нужные нам исполняемые файлы. Теперь загрузка платформы целиком в наших руках, но только в случае, если пароль на BIOS стойкий и не хранится открытым текстом [17], как у некоторых, а в реализации SecureBoot нет каких-либо известных (или еще неизвестных) дыр. Сам по себе SecureBoot — не панацея от буткитов, но с ним ситуация с безопасной загрузкой все равно намного лучше, чем без него.
Надеюсь, что материал вам поможет, и спасибо за то, что прочитали эту портянку.

Литература

Managing EFI Bootloaders for Linux: Controlling SecureBoot [18].
AltLinux UEFI SecureBoot mini-HOWTO [19].
Booting a self-signed Linux kernel [20].
Sakaki's EFI Install Guide: Configuring SecureBoot [21].
Ubuntu Security Team: SecureBoot [22].
Owning your Windows 8 UEFI Platform [23].
MinnowBoard Max: Quickstart UEFI Secure Boot [11].
Windows 8.1 Secure Boot Key Creation and Management Guidance [10].

Автор: CodeRush

Источник [24]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/open-source/106708

Ссылки в тексте:

[1] заключительной части опуса о безопасности UEFI: http://habrahabr.ru/post/268423/

[2] со сцены ZeroNights 2015: https://twitter.com/ZeroNights/status/669864406512222208

[3] пятой части вышеупомянутого опуса: http://habrahabr.ru/post/267953/

[4] congatec conga-TR3: http://www.congatec.com/en/products/com-express-type6/conga-tr3.html

[5] conga-TEVAL: http://www.congatec.com/en/products/accessories/conga-teval.html

[6] Acer Aspire R14 R3-471T: http://www.ultrabookreview.com/6591-acer-aspire-r14-review/

[7] Dell Vostro 3360: http://www.notebookcheck.net/Review-Dell-Vostro-3360-Notebook.76737.0.html

[8] efitools: http://git.kernel.org/cgit/linux/kernel/git/jejb/efitools.git/tree/

[9] MakeCert: https://msdn.microsoft.com/library/windows/desktop/aa386968.aspx

[10] предлагается использовать HSM: https://technet.microsoft.com/en-us/library/dn747883.aspx

[11] самостоятельное изучение: http://prosauce.org/blog/2015/9/13/minnowboard-max-quickstart-uefi-secure-boot

[12] спецификации UEFI: http://www.uefi.org/specifications

[13] ссылка: http://go.microsoft.com/fwlink/?LinkId=321185

[14] Microsoft Windows Production CA 2011: http://go.microsoft.com/fwlink/?LinkID=321185

[15] Microsoft UEFI driver signing CA: http://go.microsoft.com/fwlink/?LinkId=321194

[16] утилиту RU.efi: http://ruexe.blogspot.com/

[17] открытым текстом: https://twitter.com/NikolajSchlej/status/664121100826226688

[18] Managing EFI Bootloaders for Linux: Controlling SecureBoot: http://www.rodsbooks.com/efi-bootloaders/controlling-sb.html

[19] AltLinux UEFI SecureBoot mini-HOWTO: https://en.altlinux.org/UEFI_SecureBoot_mini-HOWTO

[20] Booting a self-signed Linux kernel: http://kroah.com/log/blog/2013/09/02/booting-a-self-signed-linux-kernel/

[21] Sakaki's EFI Install Guide: Configuring SecureBoot: https://wiki.gentoo.org/wiki/Sakaki's_EFI_Install_Guide/Configuring_Secure_Boot

[22] Ubuntu Security Team: SecureBoot: https://wiki.ubuntu.com/SecurityTeam/SecureBoot

[23] Owning your Windows 8 UEFI Platform: http://blog.hansenpartnership.com/owning-your-windows-8-uefi-platform/

[24] Источник: http://habrahabr.ru/post/273497/