ext4の暗号化fsを試してみる

Linux 4.1でext4の暗号化ファイルシステムが取り込まれているのに気づいたので少し試してみました．
cCryptFSやEncFSなどと同じようにファイル単位での暗号化です．前もって暗号化フラグを設定してあれば一般ユーザが勝手に暗号領域を作ることも可能でした．eCryptFSやEncFSのような使い方も可能そうです．恐らく速度はこちらのほうが速いでしょう(未確認)．ただ，パスフレーズがわかってしまうと別のユーザからもマウント可能だしパーミッションがあれば読み書きも出来るので通常のファイルシステムと同様パーミッションの設定は必須ですね．
パーティション内全てを暗号化することは出来ないようなのでLUKS(dm-crypt)とは単純に空きかえることはできなさそうです．

そんなこんなでもともとAndroid向けということもあってPC/Serverではあまり使いみちが思いつかない感じです．(何かいい使い方ありそうだけど……．)

必要条件確認

Linux 4.1以上

$ uname -r
4.9.0-2-amd64

CONFIG_EXT4_ENCRYPTIONが有効

$ grep CONFIG_EXT4_ENCRYPTION /boot/config-`uname -r`
CONFIG_EXT4_ENCRYPTION=y

e2fsprogs 1.43以上

$ dpkg-query -W e2fsprogs
e2fsprogs 1.43.4-2

ブロックサイズが4k

$ sudo dumpe2fs /dev/loop0 | grep -i 'block size'
dumpe2fs 1.43.4 (31-Jan-2017)
Block size: 4096

必要なパッケージの導入

$ sudo apt install e2fsprogs keyutils util-linux coreutils mount

ファイルシステムの用意

今回は既存のファイルシステム内にディスクイメージを作成してそれを利用

1GBのディスクイメージの作成

$ dd if=/dev/zero of=ext4-crypt.img seek=1073741824 bs=1 count=1
1+0 レコード入力
1+0 レコード出力
1 byte copied, 0.000118528 s, 8.4 kB/s

パーティションの作成
primaryを1つ作成

$ /sbin/fdisk ext4-crypt.img

Welcome to fdisk (util-linux 2.29.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xa25a3988.

Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-2097151, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-2097151, default 2097151):

Created a new partition 1 of type 'Linux' and of size 1023 MiB.

Command (m for help): w
The partition table has been altered.
Syncing disks.

ext4でフォーマット

$ /sbin/mkfs.ext4 ./ext4-crypt.img
mke2fs 1.43.4 (31-Jan-2017)
Found a dos partition table in ./ext4-crypt.img
Proceed anyway? (y,N) y
Discarding device blocks: done
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: dc44fd43-7d7a-4dfc-87f1-dc52410e2dd1
Superblock backups stored on blocks:
32768, 98304, 163840, 229376

Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

マウント

$ sudo mount -o loop ./ext4-crypt.img /mnt
$ grep /mnt /etc/mtab
/dev/loop0 /mnt ext4 rw,relatime,data=ordered 0 0

オーナー，グループの変更

$ sudo chown `id -u`.`id -g` /mnt
$ ls -la /mnt
合計 36
drwxr-xr-x 3 mk mk 4096 4月 2 04:58 .
drwxr-xr-x 1 root root 248 3月 28 02:19 ..
drwx------ 2 root root 16384 4月 2 04:58 lost+found

ext4暗号化ファイルシステムの利用

ext4の暗号化フラグを設定

$ sudo tune2fs -O encrypt /dev/loop0
$ sudo dumpe2fs /dev/loop0 | grep -io encrypt
dumpe2fs 1.43.4 (31-Jan-2017)
encrypt

鍵の生成とキーリングへの追加

$ /usr/sbin/e4crypt add_key
Enter passphrase (echo disabled):
Added key with descriptor [07a3ce5a6ebf0396]
$ keyctl show
Session Keyring
1048296028 --alswrv 1000 1000 keyring: _ses
615559430 --alsw-v 1000 1000 \_ logon: ext4:07a3ce5a6ebf0396

※パスフレーズの入力は1回だけで確認されないので初回は特に注意．利用しはじめる前にキーリングをクリアして登録し直してパスフレーズが正しいか確認しておく．

暗号化ポリシーの設定

このとき対象ディレクトリが空ではない場合エラーとなる( Error [Directory not empty] setting policy. )ので注意．

マウントポイントにはlost+foundが存在するので必ずサブディレクトリ以下である必要がある．

$ mkdir /mnt/encryption
$ /usr/sbin/e4crypt set_policy 07a3ce5a6ebf0396 /mnt/encryption
Key with descriptor [07a3ce5a6ebf0396] applied to /mnt/encryption.

※鍵の生成とキーリングへの追加と暗号化ポリシーの設定は次のようにすることで一度に設定可能

$ /usr/sbin/e4crypt add_key /mnt/encryption

暗号化ファイルシステム領域にファイルを作成

$ echo 'hello' > /mnt/encryption/test.txt
$ ls -la /mnt/encryption
合計 12
drwxr-xr-x 2 mk mk 4096 4月 2 05:07 .
drwxr-xr-x 4 mk mk 4096 4月 2 05:06 ..
-rw-r--r-- 1 mk mk 6 4月 2 05:07 test.txt

キーリングのクリア

$ sudo keyctl clear @s
$ sudo keyctl show
Session Keyring
1048296028 --alswrv 1000 1000 keyring: _ses

キーリングをクリアしただけではアクセスできる

$ ls -lA /mnt/encryption
合計 12
-rw-r--r-- 1 mk mk 6 4月 2 05:07 test.txt

アンマウントとマウントし直し

キーリングをクリアした状態でアンマウントすると暗号化された状態に戻る

$ sudo umount /mnt
$ sudo mount -o loop ./ext4-crypt.img /mnt
$ ls -la /mnt/encryption
合計 12
drwxr-xr-x 2 mk mk 4096 4月 2 05:42 .
drwxr-xr-x 4 mk mk 4096 4月 2 05:06 ..
-rw-r--r-- 1 mk mk 6 4月 2 05:42 uzUlJZQfaxMx,7cC63,53A
$ cat /mnt/encryption/uzUlJZQfaxMx,7cC63,53A
cat: /mnt/encryption/uzUlJZQfaxMx,7cC63,53A: 要求されたキーが利用できません

ユーザ，グループ，パーミッションなどは見える．内容にはアクセスできない．

再度暗号化領域を利用出来るようにする

鍵の生成とキーリングへの追加と暗号化ポリシーの設定をし直すとアクセスできるようになる

$ /usr/sbin/e4crypt add_key /mnt/encryption
Enter passphrase (echo disabled):
Added key with descriptor [07a3ce5a6ebf0396]
$ ls -la /mnt/encryption
合計 12
drwxr-xr-x 2 mk mk 4096 4月 2 05:42 .
drwxr-xr-x 4 mk mk 4096 4月 2 05:06 ..
-rw-r--r-- 1 mk mk 6 4月 2 05:42 test.txt

ファイル名長の確認

EncFSなどはファイル名のメタデータがファイル名内にあるので利用できるファイル名長が短くなってしまう．ext4ではどうか試す．

通常のext4領域では256文字

$ touch /mnt/1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
touch: '/mnt/1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' に touch できません: ファイル名が長すぎます
$ touch /mnt/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345

暗号化領域も同様だった

$ touch /mnt/encryption/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
$ ls -lA /mnt/encryption/
合計 4
-rw-r--r-- 1 mk mk 0 4月 2 07:14 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
-rw-r--r-- 1 mk mk 6 4月 2 05:42 test.txt

非暗号化状態ではこんな状態

-rw-r--r-- 1 mk mk 0 4月 2 07:14 _OsoePJvc3qPQCPHbUMtjSynszcHig3BL
-rw-r--r-- 1 mk mk 6 4月 2 05:42 uzUlJZQfaxMx,7cC63,53A

復号状態のファイル名は別の場所に記録されているよう．

複数の暗号化領域を作ってみる

新しい暗号化領域のためのディレクトリを作成

$ mkdir /mnt/encryption2
$ ls -la /mnt/encryption2
合計 8
drwxr-xr-x 2 mk mk 4096 4月 2 06:49 .
drwxr-xr-x 5 mk mk 4096 4月 2 06:49 ..

暗号化設定

$ sudo e4crypt add_key /mnt/encryption2
Enter passphrase (echo disabled):
Key with descriptor [9640dd016062b432] already exists
Key with descriptor [9640dd016062b432] applied to /mnt/encryption2.
$ keyctl show
Session Keyring
1048296028 --alswrv 1000 1000 keyring: _ses
94779002 --alsw-v 0 0 \_ logon: ext4:69ca01e214957173
219437542 --alsw-v 0 0 \_ logon: ext4:07a3ce5a6ebf0396
1025344233 --alsw-v 0 0 \_ logon: ext4:9640dd016062b432
$ touch /mnt/encryption2/hoge

一回暗号化を解除してマウントし直す

$ keyctl clear @s
$ keyctl show
Session Keyring
1048296028 --alswrv 1000 1000 keyring: _ses
$ sudo umount /mnt
$ sudo mount -o loop ./ext4-crypt.img /mnt

片方だけ鍵を登録して暗号化領域を利用

$ sudo e4crypt add_key /mnt/encryption2
Enter passphrase (echo disabled):
Added key with descriptor [9640dd016062b432]
Key with descriptor [9640dd016062b432] applied to /mnt/encryption2.
$ ls -la /mnt/encryption*
/mnt/encryption:
合計 12
drwxr-xr-x 2 mk mk 4096 4月 2 06:11 .
drwxr-xr-x 5 mk mk 4096 4月 2 06:49 ..
-rw-r--r-- 1 mk mk 0 4月 2 06:11 _OsoePJvc3qPQCPHbUMtjSynszcHig3BL
-rw-r--r-- 1 mk mk 6 4月 2 05:42 uzUlJZQfaxMx,7cC63,53A

/mnt/encryption2:
合計 8
drwxr-xr-x 2 mk mk 4096 4月 2 06:51 .
drwxr-xr-x 5 mk mk 4096 4月 2 06:49 ..
-rw-r--r-- 1 mk mk 0 4月 2 06:51 hoge

暗号化領域に鍵が登録されてない状態でファイルを作ってみる

暗号化領域に鍵が登録されてない状態でファイルを作るとどうなるかを確認．

$ ls -lA /mnt/encryption
合計 4
-rw-r--r-- 1 mk mk 0 4月 2 07:14 _OsoePJvc3qPQCPHbUMtjSynszcHig3BL
-rw-r--r-- 1 mk mk 6 4月 2 05:42 uzUlJZQfaxMx,7cC63,53A
mk@x220:~ (1180)$ touch /mnt/encryption/test
touch: '/mnt/encryption/test' のタイムスタンプを設定中です: そのようなファイルやディレクトリはありません
mk@x220:~ (1181)$ ls -lA /mnt/encryption
合計 4
-rw-r--r-- 1 mk mk 0 4月 2 07:14 _OsoePJvc3qPQCPHbUMtjSynszcHig3BL
-rw-r--r-- 1 mk mk 6 4月 2 05:42 uzUlJZQfaxMx,7cC63,53A

エラーとなって作れない．

別のユーザで利用

別のユーザで中が見えるか確認

$ id
uid=1001(gm) gid=1001(gm) groups=1001(gm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(netdev)
$ ls -la /mnt/encryption
合計 12
drwxr-xr-x 2 mk mk 4096 4月 2 06:11 .
drwxr-xr-x 7 mk mk 4096 4月 2 07:48 ..
-rw-r--r-- 1 mk mk 0 4月 2 07:14 _OsoePJvc3qPQCPHbUMtjSynszcHig3BL
-rw-r--r-- 1 mk mk 6 4月 2 05:42 uzUlJZQfaxMx,7cC63,53A
$ ls -la /mnt/encryption
合計 12
drwxrwxrwx 2 mk mk 4096 4月 2 06:11 .
drwxr-xr-x 7 mk mk 4096 4月 2 07:48 ..
-rw-r--r-- 1 mk mk 0 4月 2 07:14 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
-rw-r--r-- 1 mk mk 6 4月 2 05:42 test.txt

権限があればファイル作成もできる

$ touch /mnt/encryption/other_user
$ ls -lA /mnt/encryption
合計 4
-rw-r--r-- 1 mk mk 0 4月 2 07:14 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
-rw-r--r-- 1 gm gm 0 4月 2 07:55 other_user
-rw-r--r-- 1 mk mk 6 4月 2 05:42 test.txt

暗号化解除は出来ないと思ったが，

$ /usr/sbin/e4crypt add_key /mnt/encryption
/mnt/encryption: Permission denied

パーミッションをゆるくしてやると出来てしまう．

$ ls -la /mnt/encryption
合計 12
drwxrwxrwx 2 mk mk 4096 4月 2 07:55 .
drwxr-xr-x 7 mk mk 4096 4月 2 07:48 ..
-rw-r--r-- 1 gm gm 0 4月 2 07:55 97NmIBETx,1q9US96etRsA
-rw-r--r-- 1 mk mk 0 4月 2 07:14 _OsoePJvc3qPQCPHbUMtjSynszcHig3BL
-rw-r--r-- 1 mk mk 6 4月 2 05:42 uzUlJZQfaxMx,7cC63,53A
$ /usr/sbin/e4crypt add_key /mnt/encryption
Enter passphrase (echo disabled):
Added key with descriptor [07a3ce5a6ebf0396]
Error [Permission denied] setting policy.
The key descriptor [07a3ce5a6ebf0396] may not match the existing encryption context for directory [/mnt/encryption].
$ ls -lA /mnt/encryption
合計 4
-rw-r--r-- 1 mk mk 0 4月 2 07:14 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
-rw-r--r-- 1 gm gm 0 4月 2 07:55 other_user
-rw-r--r-- 1 mk mk 6 4月 2 05:42 test.txt