#LUKSの基本形#
前回でu-bootまでは署名された状態で改ざんを防止したSecurebootに対応できた。
ルートファイルシステムの暗号化を検討するにあたり、LUKSに必要な要素を確認してみる。
Jetson Nano ではcryptsetupをインストールして、外付けUSBデバイスを暗号化する事例はあるようだ。
Jetson Nanoで持ち運び可能な暗号化ディレクトリの使用
r32.4.2で試してみたところ、カーネルモジュールdm-cryptのコンパイルは不要なようだった。
$ zcat /proc/config.gz | grep DM_CRYPT
CONFIG_DM_CRYPT=y
$ sudo apt install cryptsetup
上記のみでOKだった。
USBフラッシュをJetson Nanoに接続すると/dev/sdaで認識する。
新規に領域を作り暗号化してみる。
$ sudo fdisk /dev/sda
Welcome to fdisk (util-linux 2.31.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (1-4, default 1):
First sector (2048-61120511, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-61120511, default 61120511):
Created a new partition 1 of type 'Linux' and of size 29.1 GiB.
Command (m for help): w
The partition table has been altered.
Syncing disks.
これで新規に領域を作成できた。
$ sudo fdisk -l /dev/sda
Disk /dev/sda: 29.1 GiB, 31293702144 bytes, 61120512 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x49783f5b
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 61120511 61118464 29.1G 83 Linux
$ sudo cryptsetup luksFormat /dev/sda1
WARNING!
========
This will overwrite data on /dev/sda1 irrevocably.
Are you sure? (Type uppercase yes): YES<大文字YES回答>
Enter passphrase for /dev/sda1:<パスワード、ここでは"test"と入れる>
Verify passphrase: <パスワード、ここでは"test"と入れる>
これでLUKSパーティションが完成した。
LUKSパーティション内に鍵情報も保管される。
アクセスしてみる。
$ sudo cryptsetup luksOpen /dev/sda1 crypt
Enter passphrase for /dev/sda1:<パスワード、ここでは"test"と入れる>
$ ls /dev/mapper/
control crypt
cryptマッパーデバイスができている。
$ sudo mkfs.ext4 /dev/mapper/crypt
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 40472 1k blocks and 10120 inodes
Filesystem UUID: e480b75b-b80b-42a6-bddc-36b22f3b846a
Superblock backups stored on blocks:
8193, 24577
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
ext4でフォーマットした。
$ sudo mkdir /media/crypt
$ sudo mount /dev/mapper/crypt /media/crypt
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/crypt 35M 782K 31M 3% /media/crypt
この時点で/media/cryptで暗号化USBフラッシュにアクセスが可能。
アンマウントとLUKSパーティションの登録解除
$ sudo umount /media/crypt
$ sudo luksClose crypt
このように簡単に暗号化を使うことができる。
今回作成した暗号化USBフラッシュの状態を以下で確認できる。
$ sudo cryptsetup luksDump /dev/sda1
LUKS header information for /dev/sda1
Version: 1
Cipher name: aes
Cipher mode: xts-plain64
Hash spec: sha256
Payload offset: 4096
MK bits: 256
MK digest: c2 cd 56 9b 89 22 f7 94 19 2f bb 3e 5f f4 8c 18 cf fa 92 f1
MK salt: db b0 78 51 9b 16 3a a8 a5 3b 6f 04 30 4f 07 e7
78 a0 0b e9 08 12 76 5e a7 a2 b1 75 fc b5 04 d0
MK iterations: 128000
UUID: eac27503-bc3e-4fa2-85b3-48a962ec303e
Key Slot 0: ENABLED
Iterations: 2048000
Salt: 83 1f 38 56 b8 38 0b f1 2d c5 80 f8 56 35 ce bd
41 c6 5d be 3d 80 71 55 d0 1a bd ef 2b 74 3c e5
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
これによれば8個あるキースロットの0番に手打ちしたパスワード、"test"が登録されていることわかる。
#ルートファイルシステムの暗号化の際の検討事項#
今までは、起動した後のLinux内で、ユーザーのパスワード入力も行いながら特定のUSBフラッシュを暗号化したが、ルートファイルシステムの暗号化の場合、自動で安全にルートファイルシステムを復号してマウントし、Linuxに引き渡さなければならない。
1、ユーザーパスワード操作でなく、鍵ファイルで自動復号
2、Linuxの起動プロセスの間へ復号処理を割り込ませる。
上記の2つが必要。
1、ユーザーパスワード操作でなく、鍵ファイルで自動復号
これは、LUKSデバイスをオープンするためのコマンドでパスワード操作ではなく、ファイルを渡す設定を行えばいい。
具体的には上記の例でいうと
$ sudo cryptsetup luksOpen /dev/sda1 crypt
上記を変更して、
$ sudo cryptsetup luksOpen /dev/sda1 crypt --key-file=<鍵ファイル>
とすればいい。
しかし<鍵ファイル>自体を置く場所が難しい。
ルートファイルシステムの暗号化となると、ルートファイルシステム自体には鍵を置けない。
別途USBフラッシュという手もあるだろうが、鍵ファイル自体を盗まれれば意味がない。
これはどうにか隠したい。
もう一つ、パイプで鍵を渡す方法もある。
$ sudo sh -c ”echo <鍵ファイル> | cryptsetup luksOpen /dev/sda1 crypt --key-file=-”
上記の"--key-file=-"はstdinから読み取るというオプションになる。
これであれば、ファイルを置く必要、また一時的にファイルを生成する必要がなく、stdoutでデータが吐けるプログラムを作ればそれを入力させることもできる。
この方法を使い、安全な鍵データを出力するプログラムを作成してみる。
ATECC608Aの鍵を保存してあるスロットへアクセスし、IO保護キーで通信経路を暗号化しながら読み出してstdoutに出力するプログラムを作成した。
github/ECC608-keyout2
ビルドする際は、Jetson Nano上で
$ sudo apt install build-essential
$ git clone --recursive https://github.com/kmwebnet/ECC608-keyout2
$ cd ECC608-keyout2
$ make
とすると、keyoutというバイナリができる。
このプログラムの実行には別途ATECC608Aの初期化、指定スロットへの鍵の書き込みをやっておく必要があるため、後述する。
現時点では、stdoutに任意の出力があればいいということで下記のシェルスクリプトで代用してみる。
どこにでもあるチュートリアルのようなコードでいいだろう。
$ vi keyout.sh
#! /bin/bash
echo "Hello"
$ chmod +x keyout.sh
$ ./keyout.sh
Hello
これを使って、先ほどのUSBフラッシュを使いテストしてみる。
すでにキースロット0に"test"というパスワードを登録した。
人のパスワード入力をなくす設定を試してみる。
まず、keyout.shから生成される鍵を追加して登録したい。
$ echo -en "\x74\x65\x73\x74" > preset.key
$ sudo sh -c "./keyout.sh | cryptsetup luksAddKey /dev/sda1 --key-file=preset.key /dev/stdin"
手打ちで入力したパスワードは、改行コードなしのバイナリ扱いで登録されている。
よって、ただ単にecho "test" >とやって鍵ファイルを作ると、
$ echo "test" > preset.key
$ xxd preset.key
00000000: 7465 7374 0a test.
こんな風に末尾に”0a”がついて認証に失敗する。
これで数時間はまった。
実行した結果を確認する。
$ sudo cryptsetup luksDump /dev/sda1
LUKS header information for /dev/sda1
Version: 1
Cipher name: aes
Cipher mode: xts-plain64
Hash spec: sha256
Payload offset: 4096
MK bits: 256
MK digest: c2 cd 56 9b 89 22 f7 94 19 2f bb 3e 5f f4 8c 18 cf fa 92 f1
MK salt: db b0 78 51 9b 16 3a a8 a5 3b 6f 04 30 4f 07 e7
78 a0 0b e9 08 12 76 5e a7 a2 b1 75 fc b5 04 d0
MK iterations: 128000
UUID: eac27503-bc3e-4fa2-85b3-48a962ec303e
Key Slot 0: ENABLED
Iterations: 2048000
Salt: 83 1f 38 56 b8 38 0b f1 2d c5 80 f8 56 35 ce bd
41 c6 5d be 3d 80 71 55 d0 1a bd ef 2b 74 3c e5
Key material offset: 8
AF stripes: 4000
Key Slot 1: ENABLED
Iterations: 2001098
Salt: de 39 9b 4b 6b 65 4e fb 62 78 e1 e0 de c1 2e 6c
4c ab 9b 3b 0c 88 6f ee 7b 8f a8 68 dd b2 0b 48
Key material offset: 264
AF stripes: 4000
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
キースロット0の鍵で認証し、キースロット1をstdinから追加できた。
後、"test"というわかりやすいパスワードを消したい。
キースロット1の鍵で認証して、キースロット0の"test"鍵を消す。
$ sudo sh -c "./keyout.sh | cryptsetup luksKillSlot /dev/sda1 0 --key-file=-"
$ sudo cryptsetup luksDump /dev/sda1
LUKS header information for /dev/sda1
Version: 1
Cipher name: aes
Cipher mode: xts-plain64
Hash spec: sha256
Payload offset: 4096
MK bits: 256
MK digest: c2 cd 56 9b 89 22 f7 94 19 2f bb 3e 5f f4 8c 18 cf fa 92 f1
MK salt: db b0 78 51 9b 16 3a a8 a5 3b 6f 04 30 4f 07 e7
78 a0 0b e9 08 12 76 5e a7 a2 b1 75 fc b5 04 d0
MK iterations: 128000
UUID: eac27503-bc3e-4fa2-85b3-48a962ec303e
Key Slot 0: DISABLED
Key Slot 1: ENABLED
Iterations: 2001098
Salt: de 39 9b 4b 6b 65 4e fb 62 78 e1 e0 de c1 2e 6c
4c ab 9b 3b 0c 88 6f ee 7b 8f a8 68 dd b2 0b 48
Key material offset: 264
AF stripes: 4000
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
キースロット0の鍵を消すことができた。
これらの操作ができれば、鍵ファイルを置かないでluksOpenができるようになる。
2、Linuxの起動プロセスの間へ復号処理を割り込ませる。
上記で作成した安全に鍵を出力するプログラムをLinuxの起動プロセスに割り込ませる必要がある。
これはinitramfsの調査が必要になる。
次回Jetson Nano Dev Boardを使ってSDカード暗号化をテスト(initramfs 調査編)でこれを行っていきたい。
Jetson Nano Dev Boardを使ってSDカード暗号化をテスト 記事インデックス
概要編
Jetson Nano secureboot編
LUKS 調査編 <いまここ
initramfs 調査編
起動シーケンス作成編