понедельник, 9 июня 2008 г.

Блочные устройства linux, шифрование и не только...

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

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

Начать стоит с того, что cryptoloop устарел. Наверное 50% ссылок по данной теме ведут на описание cryptoloop. Причем устарел он уже несколько лет назад.

Актуальной технологией на сегодняшний день является device-mapper. Но 40% из оставшихся ссылок указывают на описание cryptsetup, который вполне позволит настроить шифрование, но наверное не более того, хотя утвеждать не буду. Для типичного использования она вполне подходит. Кроме того расширение luks позволяет хранить информацию о используемом шифровании раздела. По умолчанию никакия информация нигде не хранится, что чревато ошибками конфигурирования. стоит ошибиться в алгоритме шифрования или ввести некорректный ключ (да, информация о корректности ключа тоже нигде не хранится) и данные будут безвозвратно уничтожены.

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

Cryptsetup - это обертка над базовым механизмом, о котором и пойдет речь дальше. А базовый механизм выглядит следующим образом. В ядре существует подсистема "Device Mapper", она находится в "Device Drivers" ---> "Multiple devices driver support (RAID and LVM)". Для управления носителями сущствует пакет device-mapper, в который входит в частности утилита dmsetup. Смысл существования этой подсистемы состоит в том, что она создает блочные устройства, которые располагаются в /dev/mapper, на основании информации о целях. Причем одно устройство маппера может состоять из нескольких целевых устройств. Собственно так это мапперу и указывается. Дескать создаем линейную цель, которая займет в создаваемом девайсе сектора с 0 по 999, но сама располагается на /dev/sda со смещением в 300 секторов от начала диска.

Примерно аналогично задается и шифрованная цель. Или правильнее говорить источник? Но в терминологии DM это называется target. Только дополнительно задается алгоритм шифрования и устанавливаеся ключ. Поддерживаемые ядром алгоритмы шифрования можно посмотреть в /proc/crypto. Помимо собственных алгоритмов ядром поддерживаются некоторые режимы работы блочного шифра. ecb, cbc, pcbc. Название блочного шифра комбинируется из двух этих понятий (например aes-cbc). Кроме того для шифрованного раздела необходимо задать метод формирования вектора инициализации сектора. Инфрмацию об этих методах можно найти в исходниках (drivers/md/dm-crypt.c), вот они: plain, essiv, benbi, null. перечислять подробности не буду.

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

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

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

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

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