debian Wheezyにdm_cryptを導入

■debian Wheezyにdm_cryptの導入
 使用用途は例えば、外付けのUSBディスクのデータの暗号化。
 後述するが、読み書きの性能が低下するので、
 小さな暗号化イメージを作成して扱うのもひとつの方法。

$ sudo apt-get install -y cryptsetup
$ apropos cryptsetup
cryptdisks_start (8) - wrapper around cryptsetup that parses /etc/crypttab.
cryptdisks_stop (8)  - wrapper around cryptsetup that parses /etc/crypttab.
cryptsetup (8)       - manage plain dm-crypt and LUKS encrypted volumes

■モジュールの情報を表示。

$ sudo modinfo dm_mod
filename:       /lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-mod.ko
license:        GPL
author:         Joe Thornber <dm-devel@redhat.com>
description:    device-mapper driver
alias:          devname:mapper/control
alias:          char-major-10-236
depends:
intree:         Y
vermagic:       3.2.0-4-686-pae SMP mod_unload modversions 686
parm:           major:The major number of the device mapper (uint)

$ sudo modinfo dm_crypt
filename:       /lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-crypt.ko
license:        GPL
description:    device-mapper target for transparent encryption / decryption
author:         Christophe Saout <christophe@saout.de>
depends:        dm-mod
intree:         Y
vermagic:       3.2.0-4-686-pae SMP mod_unload modversions 686

■device-mapperはその名の通り、デバイスとして仮想ディスクを扱う。
 「dm_crypt」は暗号化の為のモジュールなので、
 一般的な暗号化、ハッシュアルゴリズムを使うのがお勧め。

$ cat /proc/devices | grep "^[BC]\|device-mapper"
Character devices:
Block devices:
254 device-mapper

$ lsmod | grep dm
dm_crypt               18039  0
dm_mod                 57362  1 dm_crypt

$ find /lib/modules/`uname -r`/ -type f -print | grep dm-
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-log-userspace.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-delay.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-mirror.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-region-hash.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-zero.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-thin-pool.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-snapshot.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-flakey.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-service-time.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-mod.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-round-robin.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-multipath.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/persistent-data/dm-persistent-data.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-queue-length.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-log.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-crypt.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-bufio.ko
/lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-raid.ko

■モジュールが有効になってない場合もあるようだ。

$ sudo apt-get install -y kernel-package
$ grep DM_CRYPT /usr/share/kernel-package/Config/config*
/usr/share/kernel-package/Config/config.apus:# CONFIG_DM_CRYPT is not set
/usr/share/kernel-package/Config/config.hppa:CONFIG_DM_CRYPT=m
/usr/share/kernel-package/Config/config.m68k:CONFIG_DM_CRYPT=m
/usr/share/kernel-package/Config/config.s3c2410:CONFIG_DM_CRYPT=m
/usr/share/kernel-package/Config/config.um:CONFIG_DM_CRYPT=m
/usr/share/kernel-package/Config/config.xen0:# CONFIG_DM_CRYPT is not set

■特殊なCPUでなければ、kernelにデフォルトで取り込まれていると考えて良さそうだ。
 コンパイルする場合は、「"Multiple devices driver support (RAID and LVM)"」の
 「"Device mapper debugging support"」を選択し、DM_CRYPTを有効にする。

$ sudo apt-get source --download-only linux-image-`uname -r`
$ tar Jtvf linux_3.2.41.orig.tar.xz | grep 'drivers/md/Kconfig'
-rw-rw---- ben/ben       12617 2013-03-21 00:03 linux-3.2.41/drivers/md/Kconfig
$ xzcat linux_3.2.41.orig.tar.xz | tar xvf - linux-3.2.41/drivers/md/Kconfig
linux-3.2.41/drivers/md/Kconfig
$ find linux-3.2.41/
linux-3.2.41/
linux-3.2.41/drivers
linux-3.2.41/drivers/md
linux-3.2.41/drivers/md/Kconfig

$ grep "bool\|^config DM_" linux-3.2.41/drivers/md/Kconfig
        bool "Multiple devices driver support (RAID and LVM)"
        bool "Autodetect RAID arrays during kernel boot"
        bool "RAID-4/RAID-5/RAID-6 Multicore processing (EXPERIMENTAL)"
config DM_DEBUG
        boolean "Device mapper debugging support"
config DM_BUFIO
config DM_CRYPT
config DM_SNAPSHOT
config DM_THIN_PROVISIONING
config DM_DEBUG_BLOCK_STACK_TRACING
        boolean "Keep stack trace of thin provisioning block lock holders"
config DM_DEBUG_SPACE_MAPS
        boolean "Extra validation for thin provisioning space maps"
config DM_MIRROR
config DM_RAID
config DM_LOG_USERSPACE
config DM_ZERO
config DM_MULTIPATH
config DM_MULTIPATH_QL
config DM_MULTIPATH_ST
config DM_DELAY
config DM_UEVENT
        bool "DM uevents (EXPERIMENTAL)"
config DM_FLAKEY

■100MBのパーティションを準備。
 ※別のcryptmountのスクリプトのデフォルトから64MB以上である方が良さそう。

$ dd if=/dev/zero of=luks.img bs=1024k count=100
100+0 レコード入力
100+0 レコード出力
104857600 バイト (105 MB) コピーされました、 2.17685 秒、 48.2 MB/秒

■暗号化パーティションの作成
 暗号化アルゴリズムをaes、ハッシュアルゴリズムをsha256、キーサイズを256とする。
 ※大文字の「YES」で無いと失敗するので注意。

$ sudo cryptsetup --verbose -y luksFormat -c aes-cbc-essiv:sha256 --key-size 256 luks.img

WARNING!
========
This will overwrite data on luks.img irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:
Command successful.


■論理パーティションの名前付けと確認

$ sudo cryptsetup luksOpen ~/luks.img luks
Enter passphrase for /home/labunix/luks.img:

$ sudo cryptsetup status luks
/dev/mapper/luks is active.
  type:    LUKS1
  cipher:  aes-cbc-essiv:sha256
  keysize: 256 bits
  device:  /dev/loop0
  loop:    /home/labunix/luks.img
  offset:  4096 sectors
  size:    200704 sectors
  mode:    read/write

■「device-mapper」に「dm_crypt」デバイスとして認識された。
 「control」は「dm_mod」が提供しているデバイス。

$ ls -l /dev/mapper/
合計 0
crw------T 1 root root 10, 236  516 19:18 control
lrwxrwxrwx 1 root root       7  516 20:06 luks -> ../dm-0

$ ls -l /dev/dm-0
brw-rw---T 1 root disk 254, 0  516 20:06 /dev/dm-0

■フォーマット形式を決める。

$ apropos mkfs | grep ext
mkfs.ext2 (8)        - create an ext2/ext3/ext4 filesystem
mkfs.ext3 (8)        - create an ext2/ext3/ext4 filesystem
mkfs.ext4 (8)        - create an ext2/ext3/ext4 filesystem
mkfs.ext4dev (8)     - create an ext2/ext3/ext4 filesystem

■ext2で初期化。

$ sudo mkfs.ext2 /dev/mapper/luks
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
25168 inodes, 100352 blocks
5017 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
13 block groups
8192 blocks per group, 8192 fragments per group
1936 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done

■「/cshare」(CryptShare)にマウントしてみる。

$ MPOINT=/cshare; \
  test -d $MPOINT || sudo mkdir $MPOINT && sudo mount /dev/mapper/luks $MPOINT
$ mount | grep cshare
/dev/mapper/luks on /cshare type ext2 (rw,relatime,errors=continue,user_xattr,acl)

■動作テスト

$ sudo fdisk -l 2>/dev/null | grep swap
/dev/sda5        40138752    41940991      901120   82  Linux swap / Solaris

$ sudo hdparm -Tt /dev/sda5

/dev/sda5:
 Timing cached reads:   1188 MB in  2.00 seconds = 594.71 MB/sec
 Timing buffered disk reads: 162 MB in  3.03 seconds =  53.41 MB/sec

/dev/dm-0:
 Timing cached reads:   978 MB in  2.00 seconds = 488.84 MB/sec
 Timing buffered disk reads:  16 MB in  3.22 seconds =   4.97 MB/sec

■ディスク上に作成した通常のスワップパーティションと比べて、
 キャッシュは80%程度、バッファは10%未満の性能。

$ echo "488.83 594.71" | awk '{print $1/$2*100"%"}'
82.1964%

$ echo "4.97 53.41" | awk '{print $1/$2*100"%"}'
9.30537%

■ヘッダのバックアップ
 LUKSで、暗号化/ハッシュアルゴリズムが「cbc-essiv:sha256」
 最後はUUIDのようだ。

$ sudo cryptsetup luksHeaderBackup luks.img --header-backup-file luks.header
$ sudo strings luks.header | head -5
LUKS
cbc-essiv:sha256
sha1
{L~x>
417053cc-72f7-45c0-9203-2d4922d199e9

■下記でも同様の確認が出来る。
 「Key Slot」数分のパスワードが設定できる。

$ sudo cryptsetup luksDump luks.img
LUKS header information for /dev/loop1

Version:        1
Cipher name:    aes
Cipher mode:    cbc-essiv:sha256
Hash spec:      sha1
Payload offset: 4096
MK bits:        256
MK digest:      54 98 43 1d a2 11 b0 0a 5b 58 7e e0 0c 3f b0 8f 1c 80 dc 60
MK salt:        07 34 a1 20 57 80 17 d7 24 ea ce 04 93 5d 1f 7b
                4c 7e 78 3e e4 d8 a4 fd 5d 22 aa 0a 2f 91 bb f6
MK iterations:  8875
UUID:           417053cc-72f7-45c0-9203-2d4922d199e9

Key Slot 0: ENABLED
        Iterations:             35996
        Salt:                   e9 75 cb e4 2a 23 40 a9 a1 4a 21 06 65 dd 16 e8
                                da fd 8d 69 0c 49 a6 f8 16 4b d9 af 7e ad c8 8d
        Key material offset:    8
        AF stripes:             4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

■UUIDの確認
 下記に見るように、実際のパーティションでは無く、
 「crypto_LUKS」のUUIDである点に注意。
 「crypto_LUKS」を通常のパーティションと同じように扱うと壊れる危険性がある。

$ sudo blkid /dev/dm-0
/dev/dm-0: UUID="2cc368ed-78a5-42a9-8bd6-53084e9cd184" TYPE="ext2"
$ sudo blkid /dev/mapper/luks
/dev/mapper/luks: UUID="2cc368ed-78a5-42a9-8bd6-53084e9cd184" TYPE="ext2"
$ sudo blkid luks.img
luks.img: UUID="417053cc-72f7-45c0-9203-2d4922d199e9" TYPE="crypto_LUKS"

■LUKSデバイスのUUIDを確認する手段は下記。
 こちらは通常のパーティションは扱えない。

$ sudo cryptsetup luksUUID luks.img
417053cc-72f7-45c0-9203-2d4922d199e9

$ sudo cryptsetup luksUUID /dev/dm-0
Device /dev/dm-0 is not a valid LUKS device.

$ sudo cryptsetup luksUUID /dev/sda5
Device /dev/sda5 is not a valid LUKS device.

■パーティションとして認識されているUUIDは「ext2」の方です。

$ ls -l /dev/disk/by-uuid/ | grep dm
lrwxrwxrwx 1 root root 10  516 20:11 2cc368ed-78a5-42a9-8bd6-53084e9cd184 -> ../../dm-0

■ファイルの作成

$ echo "Hello World" | sudo tee /cshare/test
Hello World

$ cat /cshare/test
Hello World

■アンマウント

$ sudo umount /cshare
$ sudo cryptsetup luksClose luks
$ ls -l /dev/mapper/
合計 0
crw------T 1 root root 10, 236  516 19:18 control

■再マウント

$ sudo cryptsetup luksOpen luks.img luks
Enter passphrase for /home/labunix/luks.img:
$ sudo mount /dev/dm-0 /cshare/

■パスワードをパイプしてあげると、自動マウントも可能だが、
 それでは意味が無いので注意。

$ echo "password" | sudo cryptsetup luksOpen luks.img luks