Raspberry Pi で casual な tampering ぐらいには耐える程度に secure な SDカードをつくる

# はじめに
言い訳がましいタイトルで申し訳ないところではございます
デバイスドライバ（これをどうやって悪いのと置き換えるのかが悪の起点でしたよね）が SDカード上でむき出しな上に、（最近はどうなっているのかよくしりませんが）起動時に pi アカウントのパスワードの変更までできた Raspbian で「セキュアな環境の構築」って、***鍵を掛ける習慣のない島で防犯考える***ぐらい***無理***があるのも事実です

とはいえ、Raspberry Pi で実用的な装置の構築を依頼されると「無理です」では済まず

- アカウントやクレデンシャルみたいに盗られたらまずい情報をどこに置いたらいいのか。５分間デバイスを止めてSDカードまるごとコピーされたら全部持って行かれるのに
- SDカードをコピーされて別の Raspberry Pi で起動されたらどうするのか。簡単になりすまし端末ができてしまう
- アプリケーションそのものをマリシャスなユーザーからどうやって保護するのか

特に最後の奴なんか、実はお客様自身が一番マリシャスだったという笑い事じゃない事例もございまして、別の業者に依頼してまで tamper なされますので深刻でございます
同業者の皆様、どのように御対処されておりますでしょうか？

ご参考まで私の場合、以下のように対処しております

1. 暗号化ストレージ
2. SD カードのコピープロテクション
3. Server Side Device Programing[^1]

[^1]: 私の造語です^^;。アカデミックな背景はありません。2015年の時点でこんな言葉、念のためにググってみたのですが存在してませんでした。デバイスのアプリケーションをマリシャスなユーザーから守るために危険なデバイス上に保存せず、安全なサーバー上に保存して必要時に都度、サーバからデバイスに push して使う、というアイデアです。いろいろな実装方法があります

ID やクレデンシャル、センサーで取得されたデータを、SDカードごと一気にコピーされる事を 1. で防ぐ
コピーした SD カードで別の Raspberry Pi を起動する事を 2. で防ぐ
私のアプリケーションを3. で守る

このような話にどの程度ニーズがあるのかよくわからないので本稿は試しに 1. についてのみご紹介させていただければと存じます
2. と 3. については future works とさせていただければ幸いです

# 暗号化ストレージ
一言で言ってしまうとサーバでよく使われる LUKS を Raspberry Pi の SD カードでも使ってます、というだけの話でございます

暗号化されたパーティションは悪意の第三者にコピーされても中身を見ることはできません
マウントした後は普通のストレージと同じように使うことができます
なので、起動後に悪い人にログインされると無力ですが、ssh とかで守れているという前提ではセキュアであるあたりが、タイトルの「casual な tampering ぐらいには」につながっています


#組み込みデバイスでの利用実績
サーバではなく組み込み Linux で暗号化ストレージを使うのは実はかなり昔から casual attack を防ぐ目的でいろいろと使っていて、たとえば有料動画の再生アプリとかがコンテンツの暗号鍵とか、復号後のコンテンツ自体をセキュアに保存する目的で使ってたりしてました

私自身も Raspbian 上に暗号化パーティションをつくってそこに置いたアプリケーションを５分間隔で実行するようなアプリケーションを何年も前からお客様にご提供しておりますが、暗号化ストレージが原因で起きたトラブルはまだ一件もありません

# 暗号化ストレージの作り方
詳細につきましては Qiita の先輩諸兄諸姉の良い記事が洛陽の紙価を高める程潤沢に上梓されてございますので[そちら](https://qiita.com/search?q=luks)をご参照いただく事をお願いさせていただきますものと致しまして、Raspberry Pi に特有の注意点を何点かご紹介させていただくのに留めさせていただきます

## パーティションの操作は Raspberry Pi 自身でやったほうが便利だし安全です
これまでも[こちら](https://qiita.com/UedaTakeyuki/items/1b9708cd40d5f83d4b7c)とかでご説明させていただきましたが、Raspbina の SD カードのパーティションの操作は Raspberry Pi 自身でやったほうが楽ですし安全です

## 暗号化パーティションは mmcblk0p2 をずらして mmcblk0p1 と mmcblk0p2 の間に作ったほうが自由度が高いです

こんな感じで、Linux のファイルシステムが入っている mmcblk0p2 を後ろにずらして、できた隙間に
セキュアストレージを作るように一手間かけておくと
![2018-11-26 11.06.37.jpg](https://qiita-image-store.s3.amazonaws.com/0/46544/e8562dc0-2af8-255c-1c25-79261992eb8c.jpeg)

サイズの大きい SD カードで使う時に、Linux のパーティションのサイズを広げるのが楽です
それはそうとして、凄いモアレってる...

## 暗号化ストレージのマウントに crypttab とか絶対に使わない
Server だと起動時に crypttab ファイルに自動マウントするように設定を書くことが多いと思いますが、Raspbian でそんな事してると、コピーした SD カードをじっくり眺める悪意の第三者にキーファイルが簡単にバレちゃいます ^^;;; 
めんどくさくても自分で cryptsetup luksOpen する処理を書いて、これを暗号化するなり難読化するなりした上で起動シーケンスのどこかに紛れ込ませて秘すようにしておく必要があります

# threat of validity
## internal validity： 暗号化ストレージなんか使わなくても単に個々のファイルを個別に暗号化すればいいんじゃないか
SDカードごとごっそりコピーされると個々のファイルを暗号化するプログラムまで持っていかれるので、ここから鍵をみつけられる可能性があります
鍵をとられないように C や C++ で書いてきっちりと [obfuscation](https://qiita.com/UedaTakeyuki/items/4dd32bee474433af4b6e) しておくのが本手なんだと思うのですがコストが高くついてしまいます
Bash だと [shc](https://qiita.com/UedaTakeyuki/items/26293a28d15af3db77a9) があるのですが、Python とかだと効果的な [obfuscation](https://qiita.com/UedaTakeyuki/items/4dd32bee474433af4b6e) の手段を私はまだ見つけられていません
プログラムごと暗号化ストレージに置いておけばカジュアルに保護することができます

## external validity: 暗号化ストレージがあればそれで対タンパーは完全なんじゃないか
暗号化ストレージはマリシャスな第三者からデータを直接盗まれることは防げますが、その SD カードを別の Raspberry Pi に刺して起動されてしまうと正常にマウントされてしまうので、ssh で守っているとはいえすこし心許ないです
***コピープロテクト***と組み合わせて、コピーした SD カードからの起動をブロックしてしまうことでかなり安心になります

そもそも暗号化ストレージはマリシャスな第三者からデータを盗まれることは防げますが、なりすましに対して無力です

例えば、センサーから取得したデータを暗号化ストレージに溜めながらサーバに送信するデバイスを考えます

取得したセンサデータやサーバのアカウント情報をSDカードごとコピーされてしまう事は暗号化で確かに防げています
しかし、コピーされた SD カードを別の Raspberry Pi に刺して起動すると、起動時に正常にマウントされて起動してしまい、同じサーバーに別の場所からデータを送信してしまいます

これを防ぐには、アプリケーション側で***デバイスの固有ID を個別にチェック***するか、コピーされたSDカードからはそもそも起動しないように***[コピープロテクト](https://qiita.com/UedaTakeyuki/items/a2611c27fc89e698be12)***をかけてしまう事が必要になります


# reference implementation
2018-10-09 version の raspbina stretch lite （2018.11.26時点でさえすでに一個前のバージョンですね ^^; どうもすみません）に 256MByte のセキュアストレージを前述の写真のように用意して、起動時にこっそりと /home/pi/secure_strage にマウントする SD カードのイメージを [こちら](https://payhip.com/dashboard) の payhip にご用意させていただきましたので、セキュリティの評価などにご利用いただければ幸いです

評価の過程でこの暗号化ストレージの暗号鍵を見事に見抜かれてしまった豪の方には、どうやって見つけたのかおしえてくれれば先着１名で100円の賞金を差し上げます ^^/

# future works
ここまで書いておきながら、あまり刺さる人のないような話題を紹介してしまっているのではないかと今更ながら心配になっている小心者です
コピープロテクションや SSDP については本稿にもニーズがあって、例えばいいねが２桁つくような事があった場合に改めて起筆を考えさせていただくということにしてやっぱり保留にさせていただければ幸いです

ついでみたいで申し訳ないのですが、同業者の皆様はどのようにされているのかありがたく教えていただければ本当にありがたいです

あと、「この記事酷い」というお叱りにつきまして「-1」ではじまるコメントで奇譚のないご意見をいただければ、いいねの数から引いて前述のデシジョンに利用するようにさせていただきます次第です

# (2020.11.15追加)　コピープロテクション
たくさんのいいねをありがとうございます。SDカードのコピープロテクションですが、アプリケーションを特定の SD カードからしか起動できないようにする、ガラケー時代の懐かしい [SDバインド](https://www.sdcard.org/jp/developers/overview/sd_apps/sd-binding/index.html) みたいなことが、/sys ファイルを通して CID を簡単に読むことが出来る RaspberryPi だと簡単にできます。実際にご利用いただける anti-piracy の実装を[こちら](https://koshinto.uedasoft.com/docs/)に用意いたしましたので、ご遠慮なくご利用いただければ幸いです
詳細はこちらの[アドベント](https://qiita.com/advent-calendar/2020/raspberry-pi)に[記事](https://qiita.com/UedaTakeyuki/items/a2611c27fc89e698be12)をかかせていただきました

# 2023.09.01 補足
256MByte の暗号化パーティションを起動時に自動的にマウントするように設定済の Raspbian stretch lite の SD Card イメージを [payhip](https://payhip.com/b/YCQJ) で公開していますので、時間が無い方、自分で手を動かしたくない方などのお役にたつことがあればと存じます