1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Raspberry PiでSDカード暗号化をテスト

Last updated at Posted at 2023-08-08

■動機

以前、Jetson NanoでSDカード暗号化のテストを実施した。
2023年現在のRaspberry Piのセキュリティ対策方法を確認するため検証した。

■目指した状態

  1. Raspberry PiのSDカードを暗号化し、SDカードをコピーされて内容を見られることを防ぎたい。
  2. 暗号化をLUKS+cryptsetupを利用して行うが、手動でLUKS鍵を入力するのではなく、自動で鍵を入力させたい。
  3. 鍵入力を自動で行うが、LUKS鍵データをそのままフラッシュに配置しないようにする。
  4. 複数台を展開した際に、LUKS鍵データが共通にならないようにしたい。

■セキュアエレメントについて

以下は、ChatGPTにまとめてもらった内容となる。

ATECC608の主な特徴:

楕円曲線暗号(ECC): ATECC608は、楕円曲線Diffie-Hellman(ECDH)や楕円曲線デジタル署名アルゴリズム(ECDSA)など、ECCに基づく暗号化操作を高速に実行できます。

ハードウェアキーストレージ: デバイスには、プライベートキー、証明書、またはその他のセキュアデータのセキュアなストレージとして使用されるセキュアなスロットが複数含まれています。

物理的耐タンパ性: デバイスは、物理的または電気的な侵入に対して耐性があります。

セキュアブートサポート: ATECC608は、システムのセキュアブートプロセスをサポートし、起動時にファームウェアの整合性を確認するのに役立ちます。

ランダム数ジェネレータ: 高品質の真のランダム数ジェネレータ(TRNG)を搭載しています。

I2C/SWIインターフェース: 標準の通信プロトコルを使用してホストマイクロコントローラとの通信が可能です。

小さなフットプリント: 超小型のパッケージングオプションが利用可能で、様々なアプリケーションに組み込むことができます。

消費電力が低い: IoTデバイスやバッテリー駆動のアプリケーションに適しています。

これらの特徴により、ATECC608は、IoTデバイスやその他のアプリケーションでのセキュアなデータ保護、デジタル署名、暗号化通信の確保などに使用されます。

■実装

鍵保護のため、ATECC608Bセキュアエレメントを使用して以下のように考えてみた。

  1. Raspberry PiのSDカードを暗号化し、SDカードをコピーされて内容を見られることを防ぎたい。
  2. 暗号化をLUKS+cryptsetupを利用して行うが、手動でLUKS鍵を入力するのではなく、自動で鍵を入力させたい。

→ 自動で鍵を入力させ、マウントまで行うためにinitramfsとcryptsetupを利用する。
また、ATECC608Bにアクセスするための実行ファイルをビルドし、組み込む。
コードはGithubに配置した。
apt updateが走ると、initramfsの作り直しが起こり、設定が飛んでしまうことを防ぎたい。

  1. 鍵入力を自動で行うが、LUKS鍵データをそのままフラッシュに配置しないようにする。
  2. 複数台を展開した際に、LUKS鍵データが共通にならないようにしたい。

→ この要件は、ATECC608Bへ乱数でAES鍵を作成し保存、その鍵へハッシュを入力し、出力をそのまま鍵として使う方法を考えた。
ハッシュの材料は、Raspberry Piボードが固有で持っているシリアル番号をSHA-256に通して得ることとし、複数台を展開しても鍵が同一となることを避ける。
これにより、特定のRaspberry Piボード、SDカード、ATECC608Bのセットがペアリングされる。

マスターイメージとしてrootfs.imgを作成し、初期鍵を設定するが、実機に展開して1回目の起動時に

  • 初期鍵を使ってアクセスし、ATECC608Bを通った鍵を登録
  • 初期鍵を削除
    上記の動作を行うことで、ATEC608Bを通った鍵のみが登録された状態を作る。

image.png

■環境:

Raspberry pi 4 4GB 1台(以下Raspberry Pi)
ATECC608B-SSHDA(i2c接続タイプ)(以下ATECC608B)
128GB MicroSDカード
USB-MicroSDカード変換アダプター
Ubuntu22.04のインストールされたPC(以下Ubuntu PC)

■デバイスセットアップ

Raspberry PiとATECC608Bセキュアエレメントは以下のように接続した。

image.png

■イメージ作成

Ubuntu PCでRaspberry pi imagerを使い、USB-MicroSDカード変換アダプターを使ってMicroSDカードへ64ビットのOSを書き込む。

image.png
image.png

書き込み後、Raspberry Piで起動させずにそのままUbuntu PCにUSB-MicroSDカード変換アダプターを差し込み直すと、/media/<ユーザー>/bootfs /media/<ユーザー>/rootfsとしてマウントされる。

image.png

■暗号化されたrootfsを作る

Ubuntu PC上で、以下を実行する。

$ dd if=/dev/zero of=rootfs.img bs=1M count=0 seek=4000 
$ sudo losetup -f rootfs.img 
$ losetup -l 
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                         DIO LOG-SEC
/dev/loop17 #rootfs.imgがマウントされたloop<番号>を記憶しておく
             0      0         0  0 /home/<ユーザー>/rootfs.img 

$ sudo cryptsetup luksFormat /dev/loop17 #rootfs.imgがマウントされたloop<番号>

#鍵登録をする際、初期鍵として"kmwebnet"と打ち込む

$ sudo cryptsetup luksOpen /dev/loop17 luks #rootfs.imgがマウントされたloop<番号>
$ sudo mkdir /media/luks
$ sudo mkfs.ext4 /dev/mapper/luks
$ sudo mount /dev/mapper/luks /media/luks
$ sudo rsync -axHAWX --numeric-ids --info=progress2 /media/<ユーザー>/rootfs/ /media/luks

#luksの中身のfstabを以下に書き換える。
$ sudo vi /media/<ユーザー>/rootfs/etc/fstab
proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
/dev/mapper/luks	/	ext4	defaults,noatime 0 2

#後片付け
$ sudo umount /media/luks
$ sudo cryptsetup luksClose luks
#設定確認
$ sudo cryptsetup luksDump /dev/loop17 #rootfs.imgがマウントされたloop<番号>
LUKS header information
Version:       	2
Epoch:         	3
Metadata area: 	16384 [bytes]
Keyslots area: 	16744448 [bytes]
UUID:          	bd9613a6-d322-414d-91de-9fae5acec5f5
Label:         	(no label)
Subsystem:     	(no subsystem)
Flags:       	(no flags)

Data segments:
  0: crypt
	offset: 16777216 [bytes]
	length: (whole device)
	cipher: aes-xts-plain64
	sector: 512 [bytes]

Keyslots:
  0: luks2
	Key:        512 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      argon2id
	Time cost:  6
	Memory:     1048576
	Threads:    4
	Salt:       c3 df f3 b0 9f f2 93 b9 d5 7a e7 0f 27 7a 14 ce 
	            14 6f ed b8 23 ba 52 60 69 45 82 95 f5 5c 1a 5a 
	AF stripes: 4000
	AF hash:    sha256
	Area offset:32768 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
	Hash:       sha256
	Iterations: 333516
	Salt:       83 11 81 9f 35 44 3b 36 2f 82 05 a6 0f e2 d0 2a 
	            08 08 bb b5 1a eb 99 49 32 da 5d 62 41 e1 d2 8b 
	Digest:     fb 6f 18 b3 d4 0f 0f d7 d5 35 42 86 ff e1 1c fa 
	            63 be ce 09 5f 1a c3 57 66 38 54 04 8c 28 5c 44 

$ sudo losetup -d /dev/loop17 // rootfs.imgがマウントされたloop<番号>

■initramfs作成

SDカードをRaspberry Piにさして、起動させる。初回セットアップ後、以下を実行

$ sudo apt install libssl-dev cryptsetup
$ sudo raspi-config #raspi-configでi2cを有効にする。
$ git clone https://github.com/kmwebnet/cryptsetup-pi4.git
$ cd cryptsetup-pi4/
$ sudo ./intramfssetup.sh
$ sudo shutdown -h now

SDカードを取り外し、Ubuntu PCにUSB変換で接続すると勝手にマウントされるのでマウント解除。

$ fdisk -l
Disk /dev/sdb: 115.31 GiB, 123815854080 bytes, 241827840 sectors
Disk model: SD/MMC          
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: 0x95789778

Device     Boot  Start       End   Sectors   Size Id Type
/dev/sdb1         8192    532479    524288   256M  c W95 FAT32 (LBA)
/dev/sdb2       532480 241827839 241295360 115.1G 83 Linux

$ sudo dd if=/dev/sdb1 of=/home/<ユーザー>/bootpart.img
524288+0 records in
524288+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 18.9553 s, 14.2 MB/s

これでマスターイメージが出来上がった。

■展開

別のSDカードを用意しUbuntu PCからクローン。省略してあるがパーティションは設定しておく必要がある。

$ sudo dd if=/home/<ユーザー>/bootpart.img of=/dev/sdb1 
524288+0 records in
524288+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 137.626 s, 2.0 MB/s
km@km-vmware:~$ sudo dd if=/home/<ユーザー>/rootfs.img of=/dev/sdb2 bs=4M status=progress
4194304000 bytes (4.2 GB, 3.9 GiB) copied, 176 s, 23.8 MB/s
1000+0 records in
1000+0 records out
4194304000 bytes (4.2 GB, 3.9 GiB) copied, 387.595 s, 10.8 MB/s

実機にて起動。初回起動はLUKS鍵の入れ替え作業が入り、時間がかかる。

$ df -h
ファイルシス     サイズ  使用  残り 使用% マウント位置
udev               1.6G     0  1.6G    0% /dev
tmpfs              380M  1.3M  379M    1% /run
/dev/mapper/luks   117G  3.4G  109G    3% /
tmpfs              1.9G     0  1.9G    0% /dev/shm
tmpfs              5.0M  4.0K  5.0M    1% /run/lock
/dev/mmcblk0p1     255M   47M  209M   19% /boot
tmpfs              380M   20K  380M    1% /run/user/1000

ルートファイルシステムが/dev/mapper/luksとなっており成功。
自動的にパーティションの全体を使う形となっている。

実機で起動した後、以下を実行。

$ sudo apt install libssl-dev cryptsetup
$ sudo raspi-config #raspi-configでi2cを有効にする。
$ git clone https://github.com/kmwebnet/cryptsetup-pi4.git
$ cd cryptsetup-pi4/
$ sudo ./intramfssetup.sh

これでカーネルアップデートなどの、initramfsの更新時にも追従できる状態になった。

■展望

完全な信頼の連鎖(Chain of Trust)を実現するには、ブート開始時からのフラッシュ暗号化+セキュアブートが必要となるが、Raspberry PiではRaspberry Pi 4からブート領域のフラッシュ暗号化は対応していないものの、セキュアブートに対応しているようだ。

今回のテストから、さらにセキュアブートにつなげられるか試行したい。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?