Jetson Nano Dev Boardを使ってSDカード暗号化をテスト(概要編)

#きっかけ#
IoTデバイスが高度化し、処理能力が向上することで、様々なタスクがこなせるが、管理者の離れたところで稼働するデバイスに保存しているファームウェアの覗き見、資産となるデータの盗難などを防ぎたい。
特にストレージ容量、処理能力ともにリッチなLinuxデバイスのファイルシステムを暗号化したいケースが想定される。

Jetson Nanoが複数台手元にあるので、これを使ってLinuxで動作するIoTデバイスのファイルシステム暗号化を学んでみる。

#暗号化調査#
Raspberry Piでは、SDカードの暗号化を実現するサードパーティの製品があるようだ。
Zymbitという製品で、Raspberry Piのi2cインターフェースに接続し、ATECC608Aを使った鍵管理が行える製品で、機能の一つにLUKSと統合したルートファイルシステムの暗号化機能を提供している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/5e4860fc-2d05-9d74-dc36-c393098d1a3e.png)

[Zymbitサイトから引用：](https://community.zymbit.com/t/encrypting-your-root-file-system-on-raspberry-pi-using-luks-dm-crypt/150)
LUKS (Linux Unified Key Setup) は、Linux でのブロックデバイス暗号化のデファクトスタンダードである dm-crypt 用の一般的な鍵管理セットアップです。

LUKS は、複数のユーザ (およびサービス) が Linux の 'dm-crypt' インフラストラクチャにインターフェイスし、アクセスするための堅牢で柔軟なメカニズムを提供します。

dm-crypt は Linux カーネルのバージョン 2.6 以降の透過ディスク暗号化サブシステムであり、デバイスマッパーインフラストラクチャの一部であり、カーネルの Crypto API の暗号化ルーチンを使用しています。どちらもITコミュニティで広く使われ、理解されています。

単一マスターキーの弱点

dm-crypt は、ブロックの内外のデータを暗号化/復号化するために使用される単一のマスターキーを持っています。長期的なセキュリティを確保し、権限のあるユーザやサービスの変更に対応するためには、マスターキーを頻繁に変更し、複数のユーザやサービスと定期的に共有する必要があります。マスターキーを新たに繰り返すたびに、基礎となるデータブロックを毎回再暗号化する必要がある。実際のシステムでは、異なるユーザやサービスが接触するため、これは非現実的である。

階層的な鍵管理

より実用的な解決策としては、階層的な鍵管理のセットアップがあり、ユーザー/サービスにはマスターキーを解放するために使用されるユーザーキーが与えられます。ユーザー・キーは、基礎となるデータ・ブロックを再暗号化することなく、簡単に変更・失効させることができる。
このようなヒエラルキー管理者の管理はLUKSの役割です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/34149df1-0f8b-5160-120e-12cfeaf4f21a.png)
絵にしてみるとこういうことらしい。
デバイスマッパー層は、ソフトウェアRAIDなどをやる層で、そのレイヤーでブロックデバイスのIOを捕まえて暗号化、復号を行う仕組み。

Linuxシステム側に要求されることは、カーネルでのdm-cryptのサポート、およびcryptsetupパッケージのインストールとなるようだ。

#鍵を隠すための鍵―chain of trust#
上記のLUKSも、当然鍵が必要で、人の操作が介在できないIoTデバイスでは、どこかに隠さなくてはいけない。
鍵を置ける安全な領域→さらにその領域を保護する仕掛け・・・
という風に信頼関係を構築しなければならないらしい。
これを”Chain of Trust”という。日本語だと「信頼の連鎖」だろう。

IoTデバイス内で実現するには下記のような仕組みが必要となるイメージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/7d0308af-6287-2c80-da5f-ee60305989d2.png)

ブート進行順に起動処理が進んでいくが、1→2、2→3では次のステップの対象の署名を確認して起動させる。
署名の確認はどう行っているのか。
まず1→2のステップから検討。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/b4a5c5f4-ee11-5750-ac85-8c3f3a42ae20.png)

1、のブートROMはユーザーが変更できない部分でここでブート処理が始まるが、その脇にあるFUSE,OTP領域を利用してユーザーが変更できない部分に署名者の公開鍵を書き込む。
署名者とはここではファームウェアを制作した正しい開発者を指す。正しい開発者は自分だけの秘密鍵を持ち、その秘密鍵でブートローダーを署名して書き込んでおく。

起動時には、秘密鍵に対応した公開鍵をFUSE,OTP領域から読み出し、署名されたブートローダーを検証し、問題がなければブートローダーへ実行を移す。

続いて2→3について。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/77daded5-1165-5e57-6078-07b170e9dd39.png)

２、ブートローダーは前のステップで中身が改ざんされていないことが検証済みである。
その中に保存された公開鍵もまた正しいものとして扱える。
FUSE,OTP領域に書き込んだ公開鍵を引き続き使用するケースもあるようだ。
次のLinux起動フェーズで必要となる、カーネルイメージ、デバイスツリー、initramfsの3つの署名を検証し、問題なければそれらに実行を移す。
カーネルイメージ、デバイスツリー、initramfsをまとめたFlattened Image Treeという形式もあるそうで、その場合、3つをまとめて署名、検証が行える。

3→4のステップ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/df0f8eff-8fa9-31df-79e6-b9dee2fe7ddd.png)

暗号化されたアプリケーションが置かれるルートファイルシステムを復号するために、マウントする前にキースロットに対応する鍵を入力しなければならない。
この鍵は何らかの方法で秘匿、暗号化が必要。
自動でその作業を実行するため、initramfsに鍵を渡す仕掛けを施し、復号したルートファイルシステムをマウントして起動完了となる。

参考にした[Timesys の記事](https://www.timesys.com/security/secure-boot-encrypted-data-storage/)には
「セキュリティを後付けとして導入することはできません。製品デザインに組み込む必要があります。また、デバイスの起動時間、ファイルシステムのパフォーマンス、ファームウェアのアップグレードプロセスにも影響を与える可能性があるため、プロセスの早い段階で実装することを強くお勧めします。」

とある。
いろいろなアプリケーション、機械学習タスクの実行評価の前に基本的な暗号化を実装しておくことは重要だと言える。

次の記事以降でJetson Nanoで実装をテストしてみる。
[Jetson Nano Dev Boardを使ってSDカード暗号化をテスト(Jetson Nano Secureboot編)](https://qiita.com/kmitsu76/items/006845e770de24a9485e)

Jetson Nano Dev Boardを使ってSDカード暗号化をテスト　記事インデックス

[概要編](https://qiita.com/kmitsu76/items/de6bcf96b48a3bde95cc) <いまここ
[Jetson Nano secureboot編](https://qiita.com/kmitsu76/items/006845e770de24a9485e)
[LUKS 調査編](https://qiita.com/kmitsu76/items/b9c056d5f056bc8305b3)
[initramfs 調査編](https://qiita.com/kmitsu76/items/8b69f158752ff8091bde)
[起動シーケンス作成編](https://qiita.com/kmitsu76/items/2523c97ade184b94c459)