id: Гость   вход   регистрация
текущее время 19:17 25/04/2024
Автор темы: Гость, тема открыта 05/04/2015 19:27 Печать
Категории: инфобезопасность, защита дисков
создать
просмотр
ссылки

Шифрование дискет


Похоже что для шифрования дискет LUKS не подходит, т.к. его заголовок больше доступного дискового пространства 1.44 МБ. cryptsetup luksFormat работает без предупреждений, но luksOpen выдаёт сообщение о нехватке места. Можно ли уменьшить размер заголовка? Среди штатных опций такой возможности не обнаружил.


Если LUKS не подходит, какие другие варианты лучше соответствуют – EncFS, ecryptfs, loop-aes? В идеале безсигнатурное шифрование, хотя сомневаюсь что существует удобное решение, поэтому такое условие не обязательно.


 
На страницу: 1, 2, 3, 4, 5 След.
Комментарии
— pgprubot (22/05/2015 10:34, исправлен 22/05/2015 10:41)   профиль/связь   <#>
комментариев: 511   документов: 2   редакций: 70

Идея проста и понятна: LUKS-том состоит из заголовка и данных. Заголовок можно бессигнатурно (plain mode) зашифровать тем же самым паролем, что и сам LUKS, тогда сигнатур не будет вообще. При смене пароля нужно будет расшифровать заголовок, поменять LUKS-ключ в слотах на новый, а потом им же (т.е. тем же паролем) перешифровать заголовок LUKS'а (затереть, потом из бэкапа восстановить правильный заголовок, но уже на новый пароль в бессигнатурном шифровании). Этим достигается решение задачи, где есть всё:


  1. Отсутствие двойного шифрования.
  2. Отсутствие сигнатур.
  3. Cменяемость ключа на устройство через LUKS.
  4. Возможно быстро удалить данные с устройства, затерев его заголовк.
  5. Достаточно помнить всего один стойкий пароль для доступа к устройству.

Минус в том, что


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

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

— pgprubot (06/10/2015 19:38, исправлен 06/10/2015 19:46)   профиль/связь   <#>
комментариев: 511   документов: 2   редакций: 70

На каком-то уровне протестированный пример:

#!/bin/sh
 
Device=YOUR_DEVICE
 
HeaderSize=4096
FullSize=$(blockdev --getsz $Device)
Size=$(( $FullSize - $HeaderSize ))
 
cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -b $HeaderSize \
  plainOpen $Device header_crypt
cryptsetup -q -c aes-xts-plain64 -s 512 -h sha512 --align-payload 0 \
  luksFormat /dev/mapper/header_crypt
 
dmsetup create device_space --table "0 $Size linear $Device $HeaderSize"
cryptsetup --header /dev/mapper/header_crypt --align-payload 0 \
  luksOpen /dev/mapper/device_space device_space_crypt
cryptsetup remove header_crypt
 
mkfs.ext4 /dev/mapper/device_space_crypt
mount /dev/mapper/device_space_crypt /media/mnt
(как подключать и отключать устройство — понятно из контекста). В принципе, в cryptsetup 1.6.7 это должно работать, и скрипт даже, возможно, удастся упростить (поначалу пришлось делать dmsetup, т.к. luks{Open,Format} не поддерживают --offset, но сейчас вспомнил про --align-payload — его можно применить для этих целей). В 1.6.6 это тоже работает, но на основном устройстве /dev/mapper/device_space всё равно адресация идёт с дополнительным оффсетом, т.е. --align-payload игнорируется: если он задан нулевым, то по факту будет 4096. Играя со значениями, можно его увеличить или чуть-чуть уменьшить, но он всё равно будет больше, чем 4000 секторов, поэтому нет смысла указывать эту опцию. А как это работает в 1.6.7 — протестировать не могу.


Всему виной, как всегда, баги:


On 12/16/2011 08:14 AM, Arno Wagner wrote:
To my surprise, giving alignment --align-payload=1 (or = 2) results in a data-area staring at 0x101000, while --align-payload=0 gives 2MiB offset. Is this rounded up to multiples of 8? I had a brief look into the sources but did not find the relevant code. The full behaviour should go into the man-page under the explanation for --align-payload.

Align 0 should switch to internal default (4k).


Man page needs rewrite and many grammar and wording fixes...

See explanation in commit. In short, if you want detached header, you can either use data offset 0 (so whole data device is used) or there is always "reserved" space on data device of header size.

Allow to use --header option in all LUKS commands. The --header always takes precedence over positional device argument.

Disallow explicit small payload offset for detached header.

LUKS detached header has some limitations, one of them is that you cannot run some explicit check for data offsets without providing also data device.

Because luksDump and all key handle commands takes only metadata device (LUKS heaer device), it not easy to properly support data payload offset validation.

So if detached header is present for luksFormat, code now allows data payload 0 (IOW whole data device is used) and explicit offset larger than header+keyslots (the same as the header is on data device – so some space is wasted).

N.B. with detached header the option --align-payload is used directly without any round up caculations.

Fixes Issue#155.

В версии 1.6.6 ненужный оффсет можно удалить таким хаком:

#!/bin/sh
 
Device=YOUR_DEVICE
 
HeaderSize=4096
FullSize=$(blockdev --getsz $Device)
 
cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -b $HeaderSize \
  plainOpen $Device header_crypt
cryptsetup -q -c aes-xts-plain64 -s 512 -h sha512 \
  luksFormat /dev/mapper/header_crypt
 
dmsetup create device_space_full --table "0 $FullSize linear $Device 0"
cryptsetup --header /dev/mapper/header_crypt \
  luksOpen /dev/mapper/device_space_full device_space_crypt
cryptsetup remove header_crypt
 
mkfs.ext4 /dev/mapper/device_space_crypt
mount /dev/mapper/device_space_crypt /path/to
Т.е. при адресации основного пространства берём всё исходное устройство. Непосредственно его указать, правда, не получится, поэтому приходится создавать его dmsetup-алиас /dev/mapper/device_space_full, который уже используется для luksOpen.


Не самый тривиальный момент (и плохо описанный в документации) — то, что аргументом luksFormat является внешнее устройство (или файл) для хидера, а не то целевое блочное устройство, которое мы будем шифровать. Последнее вообще в этом случае не указывается в luksFormat-команде. Т.е. luksFormat создаёт только заголовок LUKS'а на чём-то (по сути — метод выведения мастер-ключа), а потом этот заголовок можно будет применять к любому блочному устройству для его шифрования. Т.е. не нужно писать --header {устройство,файл} в luksFormat-команде. man cryptsetup:


--header <device or file storing the LUKS header>
This option is only relevant for LUKS devices and can be used with the luksFormat...

For luksFormat with a file name as argument to --header, it has to exist...

Первая фраза противоречит второй. Т.е. нет такой опции --header у luksFormat — это будет ошибкой синтаксиса, если указать.


Общие замечания:


Вместо 4096 секторов можно взять любое большее число, чтобы не получить несовместимость с будущими версиями. Размер сектора (512) вряд ли в будущем изменится для обычных дисков. Вручную (без скриптов) такое подключение выполнять неудобно, да и само решение выглядит несколько грязным и переусложнённым — вероятно, нужно что-то более простое и практичное.

P.S. Ещё одна полезная заметка на тему внешних хидеров.

— pgprubot (07/10/2015 10:34, исправлен 07/10/2015 13:36)   профиль/связь   <#>
комментариев: 511   документов: 2   редакций: 70

Ввиду предыдущего комментария мотивация вполне ясна. Более-менее рабочие оттестированные варианты (применение — на свой страх и риск):


  1. Инициализация устройства, скрипт plain_init.sh:
    #!/bin/sh
    # Initialise new plain mode encrypted device on some volume group
     
    DEVICE=$1
    DEVICE_NAME=$(echo $DEVICE |sed 's/^.*\///')
    CRYPT_SLOT_NAME=${DEVICE_NAME}_slot_crypt
    CRYPT_NAME=${DEVICE_NAME}_crypt
    AMOUNT_OF_KEY_SLOTS=8
     
    echo Device name is $DEVICE
    echo Device short name is $DEVICE_NAME
    echo Crypt slot name is $CRYPT_SLOT_NAME
    echo Device crypt name is $CRYPT_NAME
    set -x
     
    # Clean all slots
    dd if=/dev/urandom of=$DEVICE bs=512 count=$AMOUNT_OF_KEY_SLOTS && \
     
    # Initialize the first slot
    cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -b 1 \
      plainOpen $DEVICE $CRYPT_SLOT_NAME && \
     
    ## Initialize the second slot
    #CRYPT_SLOT_NAME_2=${CRYPT_SLOT_NAME}_2
    #cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -b 1 -o 1 -p 1 --shared \
    #  plainOpen $DEVICE $CRYPT_SLOT_NAME_2
    #dd if=/dev/mapper/$CRYPT_SLOT_NAME of=/dev/mapper/$CRYPT_SLOT_NAME_2
    #cryptsetup remove $CRYPT_SLOT_NAME_2
     
    # Open target device
    cryptsetup -c aes-xts-plain64 -s 512 -o $AMOUNT_OF_KEY_SLOTS \
      -d /dev/mapper/$CRYPT_SLOT_NAME --shared \
      plainOpen $DEVICE $CRYPT_NAME && \
    cryptsetup remove $CRYPT_SLOT_NAME && \
     
    mkfs.ext4 /dev/mapper/$CRYPT_NAME
    Применение:
    # /path/to/plain_init.sh /dev/VG_name/LV_name
  2. Открытие устройства, скрипт plain_open.sh:
    #!/bin/sh
    # Open plain mode encrypted device on some volume group using slot 1
     
    DEVICE=$1
    DIR=$2
    DEVICE_NAME=$(echo $DEVICE |sed 's/^.*\///')
    CRYPT_SLOT_NAME=${DEVICE_NAME}_slot_crypt
    CRYPT_NAME=${DEVICE_NAME}_crypt
    AMOUNT_OF_KEY_SLOTS=8
     
    set -x
    # Open the first slot
    cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -b 1 \
      plainOpen $DEVICE $CRYPT_SLOT_NAME && \
     
    # Open target device
    cryptsetup -c aes-xts-plain64 -s 512 -o $AMOUNT_OF_KEY_SLOTS \
      -d /dev/mapper/$CRYPT_SLOT_NAME --shared \
      plainOpen $DEVICE $CRYPT_NAME && \
    cryptsetup remove $CRYPT_SLOT_NAME && \
     
    mount /dev/mapper/$CRYPT_NAME $DIR
    Применение:
    # /path/to/plain_open.sh /dev/VG_name/LV_name /path/to
  3. Отключение устройства, скрипт plain_close.sh:
    #!/bin/sh
    # Close plain mode encrypted device on some volume group
     
    DEVICE=$1
    DEVICE_NAME=$(echo $DEVICE |sed 's/^.*\///')
    CRYPT_NAME=${DEVICE_NAME}_crypt
     
    set -x
    umount /dev/mapper/$CRYPT_NAME && \
    cryptsetup remove $CRYPT_NAME
    Применение:
    # /path/to/plain_close.sh /dev/VG_name/LV_name

Количество слотов «кустарного LUKS'а» сейчас 8, это заголовок размером 4KB (у аутентичного LUKS — 4k секторов, т.е. 2 MB), но можно поставить один или два, тогда оверхед будет, соответственно, 0.5KB или 1KB. Правда, при этом mkfs.ext4 будет ругаться на выравнивание и грозиться проблемами со скоростью работы:


/dev/mapper/$CRYPT_NAME alignment is offset by 3584 bytes.
This may result in very poor performance, (re)-partitioning suggested.

чего нет при 8-ми слотах.


Открытие устройства — по сути, три команды, не требующие каких-то вычисляемых переменных, как в примере с LUKS, т.е. их легко ввести без скрипта вручную. Что ещё хорошо — для plain mode поддерживается --shared, которым не воспользоваться c LUKS (поэтому там понадобилась дополнительная команда — хак с отображением пространства с помощью dmsetup).


Для удобной смены пассфразы нужно минимум 2 слота. Пример с добавлением второго слота выше приведён (смысл понятен), но закомменчен. Т.е. расшированное содержимое всех использованных слотов-секторов одинаково (оно и есть мастер-ключ), но они зашифрованы разными пассфразами. Может возникнуть ошибка, когда в разных слотах используется одинаковая пассфраза (к примеру, в первом и во втором), тогда шифрованное содержимое у них будет одинаковым, что разрушит бессигнатурность/отрицаемость. Для этого применён трюк -o 1 -p 1 вместо просто -o 1 для второго слота. В этом случае даже при одинаковых пассфразах шифртексты будут разными. Это соответствует в точности тому, как если бы сразу расшифровали два первых слота-сектора одной пассфразой (-b 2 -o 0 -p 0) и увидели совпадение содержимого первого расшифрованного сектора со вторым на открывшемся (крипто)устройстве. Т.е. «бессигнатурный криптораздел» для второго слота-сектора состоит не из него самого, а из него + первый сектор, поэтому мы делаем отступ (-p 1) — пропускаем первый сектор, чтобы расшифровать только второй.


Возможно, есть ещё какие-то нетривиальные уязвимости схемы, но пока их не вижу. Непосредственное хранение мастер-ключа на диске (пусть и шифрованное) тоже немного смущает:


  1. Это повышает риск утечки мастер-ключа по сравнению со случаем, когда используется LUKS.
  2. Можно ли шифровать мастер-ключом мастер-ключ? Но даже если он будет где-то записан на основном шифрованном устройстве, где он используется, вряд ли это случится в первом секторе, т.е. IV всё равно будет каким-то нетривиальным.

UPD: Поскольку мастер-ключи разных криптоустройств генерятся случайным образом и всегда будут разными, plain-текст, зашифрованный в «слотах», тоже всегда будет разным (т.е. два разных криптоустройства с одинаковым мастер-ключом недопустимы). Следовательно, можно использовать одинаковые пассфразы для разных криптоустройств — ключами, выводимыми из этих пассфраз, всегда будут шифроваться разные мастер-ключи. Т.е. это предупреждение* неактуально для слотов в силу специфики их содержимого.


Кстати, в варианте с LUKS'ом какое-то частичное совпадение plain-текстов в слотах всё равно будет (хотя бы из-за общих метаданных и сигнатур), поэтому там предупреждение остаётся в силе, т.е. нельзя использовать одинаковые пассфразы для бессигнатурного слоя разных устройств.


* В plain mode одинаковые пассфразы ведут к одинаковым ключам, а одинаковые ключи на одинаковых plain-текстах дадут одинаковые шифртексты.

На страницу: 1, 2, 3, 4, 5 След.
Ваша оценка документа [показать результаты]
-3-2-1 0+1+2+3