Полнодисковое шифрование с LUKS2

Полнодисковое шифрование с LUKS2

Релиз cryptsetup 2.0 в декабре прошлого года прошел тихо и незаметно, что довольно-таки странно, если вспомнить фишки, которые он принес. В сегдошняшней статье мы постораемся разобраться, что в нем нового и какие проблемы существуют на данный момент, на деле попытаемся реализовать полное шифрование диска с использованием LUKS2, а также рассмотрим доступные коммерческие и свободные инструменты для его взлома.

Значимость и проблема FDE

Дела с шифрованием запоминающих устройств обстоят забавным образом: оно повсюду и нигде одновременно. Начиная от мобильных устройств, где оно играет особо важную роль (причем большинство пользователей об этом даже не догадываются), и заканчивая большими дата-центрами. В то же время исследования, проведенные за последние десять лет в разных странах, включая Великобританию, Германию и США, показывают, что не только обычные пользователи, но и корпорации не сильно пекутся о личных данных.

К сожалению, на этом проблемы не заканчиваются. Большинство нынешних систем полнодискового шифрования (Full Disk Encryption — FDE) обеспечивают конфиденциальность данных, но не их целостность. Это означает, что злоумышленник может физически изменить байт информации на диске и пользователь не сможет обнаружить, что и где изменилось и откуда сбои. Все потому, что сектор открытого текста равняется сектору шифротекста, а метаинформацию хранить негде.

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

Проблему целостности данных решает аутентифицированное шифрование (Authenticated Encryption with Associated Data — AEAD). Это не новая тема, и активные исследования вместе с конкурсами на лучший алгоритм (см. CAESAR) ведутся десятки лет. Но для реализации AEAD в полнодисковом шифровании нужно придумать, где хранить дополнительные данные (те самые AD).

Зачем шифровать

Если вы еще сомневаетесь, что полнодисковое шифрование — нужная штука, то подумайте вот о чем: оно не только помогает сохранить в тайне вашу очень важную инфу и пикантные фоточки, защищая вас от разного рода мошенничества и шантажа, но и предохраняет диск от изменений. Например, вас могут на какое-то время разлучить с вашим компьютером, и речь не только о «маски-шоу», но и, например, о дотошном погранконтроле. Как в таких случаях убедиться, что на диске не появилось чего-то нового? Ну и последний, чисто эмоциональный аргумент: просто представьте, какой неистовый баттхерт будет у кого-то, когда он не сможет получить доступ к вашим данным, — даже если там нет ничего интересного!

РЕКОМЕНДУЕМ:
Оценка защищенности UEFI

Решение

Ребята из Чехии несколько лет разрабатывали решение для Linux, которое сможет предоставить FDE с функцией AEAD. Главными критериями для этого были:

  • обеспечить работу без дополнительного оборудования;
  • сделать возможным применение на самых обычных дисках, которые доступны в магазине, а не по спецзаказу;
  • использовать родной размер сектора;
  • реализовать возможность восстановления данных в случае перебоя питания;
  • использовать (и писать) только свободный код и алгоритмы.

Результатом разработки стали новые объекты (targets) для device mapper: dm-integrity, обновленный dm-crypt с аутентифицированным шифрованием и формат LUKS2. Их поддержка включена в ядро Linux начиная с версии 4.12, а новые шифры AEGIS и MORUS (финалисты CAESAR) доступны с 4.18.

Подробнее о dm-integrity, dm-crypt и LUKS2

dm-integrity

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

Применяется как в паре с dm-crypt для предоставления AEAD, так и отдельно — для контроля целостности данных без шифрования. Управляется утилитами cryptsetup, если нужно шифрование, или integritysetup, соответственно, без него.

dm-crypt

Здесь добавили поддержку режимов AEAD для шифров и рандомизацию вектора инициализации (Initialization Vector). На каждую запись в сектор ядром генерируется случайный Initialization Vector.

К примеру, в режиме XTS вектор шифруется хитрым образом, что позволяет брать для него предсказуемый номер сектора (plain или plain64).

LUKS2

Это вторая версия формата LUKS с расширенными возможностями. Были устранены некоторые проблемы и ограничения, однако большинство идей LUKS1 остались. Среди новых возможностей:

  • поддержка затратных для памяти функций формирования ключа (key derivation function — KDF);
  • новый вид заголовка (бинарный + JSON), добавлен механизм контрольных сумм, дублирован (кроме области ключей);
  • ключам можно назначать приоритет;
  • JSON позволяет расширять возможности формата, не модифицируя бинарную структуру;
  • в заголовке реализованы токены, которые связаны со слотами для ключей и описывают, где взять пароль. Токены могут быть использованы для поддержки механизмов внешнего хранения ключей.

Посмотреть формат заголовка LUKS2 полностью и изучить каждое поле можно в спецификации.

Argon2 — та самая, затратная для памяти и центрального процессора KDF. В Linux доступны два варианта: Argon2i и Argon2id.

На данный момент шифры AEAD, которые есть в ядре (AES-GCM и ChaCha20-Poly1305), имеют короткий (96-bit) одноразовый код (nonce). Это означает, что вероятность коллизии слишком большая (с точки зрения криптографии) и ее нельзя игнорировать, так как использование одноразового кода дважды (nonce reuse) фатально для AES-GCM. На всякий случай отмечу, что это не касается шифрования информации, передаваемой по сети.

Для обеспечения AEAD в FDE сейчас стоит использовать новые AEGIS или MORUS. Или же AES-XTS + HMAC, если нет доступа к 4.18. Проблема этой конструкции в том, что нужно хешировать сектор, а хеширование 4 Кбайт данных занимает какое-то время. Другими словами: это долго.

Поддержка dm-integrity включается в ядре опцией CONFIG_DM_INTEGRITY. В Arch Linux проверить, включена ли она у тебя, можно командой

В Ubuntu список конфигов ядра находится в разделе /boot, файл config-версия_ядра — грепай его, и узнаешь всю правду.

Стоит упомянуть, что авторы не пытаются переизобрести велосипед и придумать невиданную ранее концепцию. Подобное решение, но с другим подходом существует во FreeBSD и называется GELI. Здесь для обеспечения целостности данных используется HMAC.

Полнодисковое шифрование с LUKS2 на практике

Итак, у нас в арсенале скоро появятся новые алгоритмы и новые фичи. Но попробовать их не терпится уже сейчас, чем я и занялся.

Работа над форматом LUKS2 еще не завершена, так что не рекомендуется использовать его в продакшене!

Тут же нас встречает первая проблема: поддержки со стороны загрузчиков просто-напросто нет. На данный момент ни GRUB, ни другие не умеют работать с LUKS2.

Отсутствие возможности грузиться с раздела LUKS2 при этом не конец света: /boot зашифруем в LUKS1. Кто-то возразит, что /boot — главный раздел и злоумышленнику, который получил доступ к нему, уже все равно, что у тебя в /. И это правда. Но к сожалению, пока что приходится работать с тем, что есть. LUKS1, конечно же, неплох, но мы сюда пришли новые фичи тестить. В любом случае LUKS2 находится в стадии допила напильником развития и модификации, поэтому о деплое в продакшен речи в любом случае не идет.

Тем временем сзади подкрался второй подвох: это ядро 4.18, которое, как ты помнишь, нужно для AEGIS и MORUS и которого на момент написания статьи нет ни в одном live-установщике. Единственная идея, которая мне приходит в голову, — это кастомный archiso, так как ежемесячный билд содержит только версию 4.17.11.

Модификация archiso

Процесс хорошо описан в Arch Wiki. В двух словах: нужно скачать официальный образ live-установщика, распаковать, внести свои изменения и запаковать обратно.

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

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

Не забудь проверить целостность файла .iso:

Проверка целостности образа
Проверка целостности образа

Так как образы ISO монтируются в режиме только для чтения, скопируй содержимое в другую директорию. Перед копированием удостоверься, что директории ~/customiso не существует, и выполни

Далее нужно распаковать airootfs.sfs утилитой unsquashfs, она есть в составе пакета squashfs-tools ( $ sudo pacman -S squashfs-tools):

Для обновления ядра понадобится… ядро. Копируй:

Теперь можно делать chroot в систему, для этого используй скрипт arch-chroot из пакета arch-install-scripts:

Для установки пакетов нужно сначала инициализировать ключи для pacman внутри chroot:

Обнови все пакеты:

В файле /etc/mkinitcpio.conf замени HOOKS=(...) на

Пересобери initramfs:

По окончании нужно создать список пакетов, почистить кеш менеджера пакетов и выйти из окружения chroot:

Перенеси свежее ядро и список пакетов, а также удали запасной образ (fallback), так как он не используется установщиком:

Создай новый airootfs.sfs, почисти мусор и сгенерируй контрольную сумму:

Чтобы можно было грузиться в режиме UEFI, надо обновить загрузочный образ:

Последнее, что нужно, — это запаковать все в новый ISO. Читай метку старого .iso при помощи lsblk -f или blkid.

Вывод команды lsblk -f
Вывод команды lsblk -f

Все готово, записывай arch-custom.iso на диск или флешку и грузись:

Установка Arch Linux на LUKS2

Если модификации прошли успешно и удалось загрузиться, то первая строчка на экране сообщит версию ядра.

Успешная загрузка модифицированного live-установщика
Успешная загрузка модифицированного live-установщика

Подробно расписывать, как устанавливать Arch Linux, нет смысла — этой информации полно в интернете. Затрону главные моменты, которые касаются LUKS2 и «прикручивания» шифрования в целом.

Установка проводится на чистый, новый или пустой диск, желательно SSD. Если у тебя есть другие разделы, то придется их нюкнуть. Также нужен UEFI, который, скорее всего, твоя машинка поддерживает.

Если ставишь на виртуалку, то главное — включить поддержку EFI и пробросить флешку.

Настройки EFI для VirtualBox
Настройки EFI для VirtualBox
Настройки USB для VirtualBox
Настройки USB для VirtualBox

Данные ОПАСНОСТЕ!!1 Единственный способ расшифровать их — это ключ-файл на флешке. Выбирай понадежней или оставь возможность ввести пароль.

Чтобы в один прекрасный день не лишиться данных из-за испорченной или утерянной флешки, сразу добавлю возможность открывать парольной фразой. Из-за этого у меня будут задействованы два слота в заголовке: пароль (слот 0) и ключ-файл (слот 1), который я добавлю потом. Если любишь риск, то можешь парольный слот уничтожить после добавления файла.

Топология диска у меня:

  • /dev/sda1 — раздел для образов .efi, не зашифрован, FAT32;
  • /dev/sda2 — раздел /boot, зашифрован, LUKS1;
  • /dev/sda3/, зашифрован, LUKS2.

GPT — таблица разделов. Отдельный /boot нужен, как ты помнишь, из-за того, что загрузчики пока не умеют открывать LUKS2. По большому счету можно избавиться от sda1 и хранить образ GRUB в файле .efi на той же флешке: для этого нужен раздел с FAT (по спецификации UEFI), и вспомнить кое-какие дополнительные ключи ( --removable) для grub-install.

Смотрю диск:

И создаю LUKS2 на /dev/sda3:

Чтобы использовать контроль целостности данных ( --integrity), на устройство сначала нужно записать контрольные суммы. Поэтому, если у тебя большой диск, придется запастись терпением.

Подготовка устройства
Подготовка устройства

А вот сравнение скорости работы алгоритмов на SSD, приведенное разработчиками. Линейная запись и чтение.

Графики сравнения скорости алгоритмов
Графики сравнения скорости алгоритмов

В качестве PBKDF я использую Argon2id. Если установка идет на одном железе, а система будет использоваться на другом, то дополнительно можно указать, сколько памяти, процессорных потоков и итераций использовать. Ключи:

  • --pbkdf-memory <number>;
  • --pbkdf-parallel <number>;
  • --pbkdf-force-iterations <num>.

Если не указывать их, то будет проведен бенчмарк текущего железа и цифры взяты оттуда.

Шифр — aegis256-random. Для LUKS2 доступны следующие алгоритмы AEAD:

  • aegis128-random;
  • aegis256-random;
  • morus640-random;
  • morus1280-random.

Суффикс -random здесь указывает на вектор инициализации. Более подробное сравнение смотри в спецификации и магистерской диссертации.

Как видно из графиков, журнал уменьшает скорость, поэтому отключаю его. На ноутбуке он, в принципе, не нужен, так как внезапная потеря питания в большинстве случаев ему не грозит.

Смотрю, что получилось, и открываю:

Содержимое заголовка LUKS2
Содержимое заголовка LUKS2

То самое эмулированное промежуточное устройство crypto_root_dif, с дополнительным местом под метаданные. Для пользователя оно прозрачно, и работа проходит с обычным блочным устройством, в данном случае crypto_root.

Новое, эмулированное устройство с контрольными суммами
Новое, эмулированное устройство с контрольными суммами

Подготовлю раздел /boot в LUKS1 и также открою его:

Тут ничего нового: любимая хеш-функция и чуть больше итераций.

Заголовок LUKS1
Заголовок LUKS1

Окей, разделы готовы. Обрати внимание: после открытия я работаю только с эмулированными устройствами /dev/mapper/crypto_boot и /dev/mapper/crypto_root, а не с физическими /dev/sda2 и /dev/sda3.

Создаю файловые системы:

Монтирую:

Всегда используй только свежие зеркала:

Для аутентификации по флешке нужно добавить дополнительный ключ. Ты можешь сделать его из последовательности битов на ней и указать GRUB использовать их при помощи следующего параметра ядра: cryptkey=device:offset:size, где

  • device — блочное устройство, на котором хранится ключ;
  • offset — смещение, по которому считывать байты;
  • size — сколько байтов считать.

В качестве device можно использовать как /dev/sdX, так и UUID=, например:

В моем случае это будет обычный файл. Поэтому воспользуюсь немного другим форматом: cryptkey=device:fstype:path и просто укажу путь к нему.

  • fstytpe — тип файловой системы, можно использовать auto;
  • path — путь к файлу.

Если флешка чистая, без разделов, то придется их создать. Какую именно файловую систему использовать — дело твое. Для экономии времени воспользуюсь установочной флешкой. Создам директорию и примонтирую в нее:

Проверка разделов флешки и монтирование
Проверка разделов флешки и монтирование

Сгенерирую ключ-файл:

[/crayon]

Статья и интересное обсуждение для тех, кто думает, что чуть выше я совершил акт кощунства.

Добавлю ключ:

Экстремалы могут удалить парольный слот командой cryptsetup luksKillSlot /dev/sda3 0, где 0 — номер слота.

Все готово к установке:

Генерирую fstab:

Далее буду проводить настройки системы изнутри. Для этого использую chroot: arch-chroot /mnt. Первым делом — GRUB. В файле /etc/default/grub раскомментируй GRUB_ENABLE_CRYPTODISK=y и замени строки

на вот такие:

Обрати внимание, что GRUB_CMDLINE_LINUX="..." — одна строка, никаких переносов нет.

Конфиг /etc/default/grub
Конфиг /etc/default/grub

Идентификаторы UUID смотри через # blkid.

Список UUID доступных в системе блочных устройств
Список UUID доступных в системе блочных устройств

Примерная схема работы:

  1. GRUB запросил пароль от раздела /boot.
  2. Пароль подходит? Открыл, прочитал его, нашел initramfs, передал ему управление.
  3. Закончил работу, все закрыл и забыл.

Параметр ядра cryptkey=UUID=5F6A-991B:auto:/root_key.bin указывает initramfs, где взять ключ от / — корневого раздела (LUKS2). Если флешка недоступна, он об этом сообщит и запросит пароль. А если ты удалил слот с паролем, то загрузиться не получится.

Файл /etc/crypttab работает схожим с /etc/fstab образом, только для зашифрованных дисков. В нем указываются все разделы (кроме корневого), которые должны быть открыты при загрузке системы. Конфиг crypttab читается перед fstab, но автомонтирование (уже открытых) разделов производит второй. Таким образом, crypttab — это то, что нужно для открытия /boot во время загрузки системы, так как GRUB, передав управление initramfs, его закрыл и забыл все ключи.

Чтобы не вводить пароль от него дважды (для GRUB и для crypttab), создай и добавь ключ-файл и для раздела /boot:

Добавляй, как обычно:

Проверим, появился ли новый слот с файлом-ключом
Проверим, появился ли новый слот с файлом-ключом

И теперь используй его для автоматического открытия. В конец /etc/crypttab допиши:

Пример моего crypttab
Пример моего crypttab

Для большей надежности перепроверь UUID в /etc/fstab. Для корневого раздела и для /boot они должны соответствовать crypto_root и crypto_boot, а не sda2 и sda3.

Записи автосгенерированного fstab
Записи автосгенерированного fstab

Осталось добавить компоненты для initramfs с помощью скрипта mkinitcpio. Для этого подредактируй файл /etc/mkinitcpio.conf и в строку

добавь encrypt, чтобы получилось

В MODULES=() допиши dm_integrity и vfat:

Иначе при загрузке получишь ошибку Kernel doesn’t support dm-integrity mapping. Модуль vfat нужен, так как раздел флешки с ключом — в FAT.

Пересобери initramfs:

Успешный пересбор initramfs
Успешный пересбор initramfs

Последнее, что нужно сделать, — это установить GRUB и сгенерировать для него .cfg-файл командами

GRUB успешно установился
GRUB успешно установился

Поздравляю, твой свежий Arch Linux установлен на раздел LUKS2 с включенным контролем целостности данных!

Парочка топорных тестов скорости дешевого SSD.

Запись и чтение на шифрованном разделе
Запись и чтение на шифрованном разделе
Запись и чтение на нешифрованном разделе
Запись и чтение на нешифрованном разделе

Проверка на прочность

Это все замечательно, но, если твой диск попадет в руки злоумышленнику, насколько тяжело (или легко) тому будет достать данные? Сейчас проверим.

Стоит понимать, что есть множество способов похитить нужную инфу. LUKS защищает данные в офлайне — то есть диск (раздел, контейнер) или закрыт, или отключен от питания вовсе. Иными словами, не думай, что, установив LUKS, ты волшебным образом навсегда обезопасишь данные. Если оставляешь компьютер без присмотра с открытым разделом или пароль записан на стикере, то извини: никакой LUKS тут не поможет.

Для тестов я выбрал четыре продукта: два открытых и два коммерческих. Открытые — это John the Ripper и hashcat. Из коммерческих я знаю продукт ElcomSoft, но он не поддерживает даже LUKS1, поэтому сразу отпадает. Второй найденный мной вариант — это Passware. Никогда не слышал об этой конторе, нашел через поисковик. Список клиентов серьезный: NASA, министерства обороны и юстиции США и другие.

Все инструменты поддерживают GPU. Фермы для майнинга, к сожалению (или к счастью), у меня нет, и в качестве GPU использовалась моя GTX 1050 Ti. Посмотрим, что может эта старушка против LUKS и LUKS2. Для взлома не нужен диск или раздел полностью, достаточно заголовка. Извлекаю их на флешку:

John the Ripper

Информация о JtR
Информация о JtR

Ставлю свежую версию и смотрю, что есть в арсенале:

Нет вывода. Окей, как насчет CPU?

Что поделать, придется довольствоваться CPU. Пробую:

JtR не поддерживает формат XTS
JtR не поддерживает формат XTS

Как видно из скриншота, даже формат AES-XTS не поддерживается, LUKS2 нет смысла пробовать. Это было быстро, идем дальше.

hashcat

Есть только LUKS первой версии. Хотя бы умеет работать с AES-XTS, проведу бенчмарк:

3217 хешей в секунду для 163 044 итераций — неплохо. У меня, если посмотреть на скриншот luksDump, — 2 941 833 для парольного слота и 2 137 768 для файла. Для hashcat недостаточно просто сделать luksHeaderBackup, нужно писать

Все шло хорошо, но тут меня ждал сюрприз в виде ошибки hashcat/OpenCL/m14651-pure.cl: No such file or directory. Как оказалось, hashcat не поддерживает хеш-функцию whirlpool. Иногда нужно читать доки до конца. На той же странице форума английскими буквами написано:

Чтобы не перебивать раздел /boot с использованием дефолтной SHA-256, создам отдельный криптоконтейнер и возьму заголовок с него, от этого ничего не поменяется.

И еще очень важная деталь: в контейнере должна быть файловая система, иначе пароль не подберется никогда, даже если он есть в списке. Это тоже упоминается на форуме по ссылке выше.

В этом заголовке другое количество итераций — 9 756 846.

Пробую и вижу один хеш в минуту и четыре секунды:

Наблюдается проблема: hashcat начинает перебирать количество итераций, пока не дойдет до нужного, а не читает его прямо с заголовка. Делает он это для каждого пароля в файле, поэтому тест для одного пароля занимает долгое время.

РЕКОМЕНДУЕМ:
Безопасность JavaScript или как написать безопасный код на JS

Passware

Из доступных на сайте продуктов я выбрал Passware Kit Forensic, полная версия стоит 995 долларов. Взял триалку, в которой время взлома ограничено одной минутой. В принципе, этого должно хватить, чтобы оценить скорость работы. Запускаю, смотрю список доступных форматов FDE.

Поддерживаемые Passware форматы FDE
Поддерживаемые Passware форматы FDE

Есть LUKS1, нет LUKS2, пробую.

Passware не поддерживает whirlpool
Passware не поддерживает whirlpool

Ситуация та же, что и с hashcat, — нет поддержки whirlpool. Беру криптоконтейнер с SHA-256, добавляю брутфорс-атаку. Чтоб сократить время ожидания до минимума, явно указываю только цифры и длину пароля.

Метод грубой силы в Passware
Метод грубой силы в Passware

В результате получаю тринадцать паролей в минуту. Если верить программе, брутфорс шестизначного цифрового пароля займет месяц и 26 дней.

Скорость взлома LUKS1 в Passware
Скорость взлома LUKS1 в Passware

Итоги

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

Удивило отсутствие поддержки whirlpool. Она в LUKS давно, видимо разработчики не любят париться и отдают предпочтение дефолтным настройкам.

По результатам видно, что стандартная PBKDF2 неплохо справляется с задачей. Возможно, перед парой сотен или тысяч GPU она не устоит, но для этого есть новый Argon2.

exit()

Радует энтузиазм разработчиков: они делают современную крипту доступной каждому и бесплатно. LUKS2 — интересный формат с кучей фишек. К сожалению, сложность конфигурации и отсутствие поддержки со стороны загрузчиков замедляет его появление на сцене. Использовать его с включенным контролем целостности данных стоит только на SSD.

Пройдет несколько лет, пока LUKS2 окрепнет и сможет полностью заменить своего предшественника. Это было с файловыми системами ext и должно произойти с LUKS2. Что до LUKS1, то он по-прежнему хорош и пока что никуда не уходит. Прекращать его поддержку не намечается, поэтому нет поводов для беспокойства.

Понравилась статья? Поделиться с друзьями:
Комментарии: 1
  1. Алексей

    Замечательная статья!
    Браво автору! У меня нет образования в сфере технологий, но читать было приятно и, в общих чертах, всё понятно.
    Спасибо!

Добавить комментарий