Raspberry PiでTPM(Trusted Platform Module)を使えるようにするまでの手順を紹介します。
Raspberry Pi自体はTPMをサポートしていないため、ソフトウェアのTPMエミュレーターを使う方法と、I2CやSPIをサポートした実際のTPM2.0チップを使う方法があります。
PCの場合はBIOSによりTPMが初期化済みであり、OSはBIOSやBootloaderから引き継いだ形でTPMを使いますが、Raspberry PiはOSが最初にTPMにアクセスするため初期化には注意が必要です。
一旦OSを通してTPMが使えるようになれば、あとの作業はPCと変わりません。この文書では、/dev/tpm0 を介してTPMにアクセスできるようになるまでの手順を示します。
以下のガイドで使用しているホストはUbuntuです。 Mac(OSX)の場合も作業ほぼ同様ですが若干の違いが有ります。OSXの方はRaspberry Pi 3 + Raspbian Jessie (2017-07-05) でTPMを使う を参照してください。
1. はじめに
IoT端末のセキュリティ向上には様々な技術が活用できます。TPMはその一つです。
| | SWの管理(コード署名、更新) | 暗号化 | TPM | 強制アクセス制御
|--------------------------|:-------:|:---:|:----:|:----:|:----:|
| 物理攻撃(中−低レベル) |☓ |○ | ◎ | ☓
| SWの改ざん攻撃 |○ |○|◎| △
| 脆弱性への攻撃 |○|☓|☓| ○
| リモートからの不正侵入 |△|☓|△| ○
TPMが出来ることは大きく2つあります。ひとつは暗号と暗号鍵の管理、もうひとつは稼働するソフトウェアの改ざん検知です。前者はHSM(Hardware Security Module)では一般的な機能です。後者はTPMのユニークな機能ですが、この機能を使いこなすにはTPMとIoTデバイス上で稼働するすべてのSWとの連携が重要になります。Raspberry Piは便利なプラットフォームですが、TPMの主要な機能である、Trusted boot や Secure boot ができません。これはRaspberry Piで最初に移動するコードがブラックボックスだからです。製品化や実運用の際にはTrusted boot や Secure boot が可能な別のプラットフォームを選択してください。ただ、開発機として様々な実験やテストで使うには十分です。
また、LinuxのTPM2.0対応はまだ十分とはいえません。この解説も順次最新の内容に更新する予定です。
1-1. ラズパイの基本設定
最初にラズパイ3の機材の調達から基本的なソフトウェア環境のセットアップまで準備を簡単に説明します。ヘッドレス(LCDモニターやキーボード無し)での操作を前提としていますが、LCDモニターやキーボードがある場合はシリアルの設定などは不要です。
1-1-1. ハードウェア(すべて秋月電気等で揃います)
- Raspberry Pi 3(できれば2よりも3が快適、このガイドは3を対象にしています)
- 本体 http://akizukidenshi.com/catalog/g/gM-11425/ (¥4800円)
- ヒートシンク (カーネル再コンパイル時にかなり熱くなります)
- ケース
- Raspberry Pi 用電源(5V, 3A)
- MicroSDカード (サイズは8GB以上、お好きなもので)
- シリアル接続用のUSB-UARTアダプタ、接続ケーブル(3.3V対応であれば、お好きなもので)
- USB-UART http://akizukidenshi.com/catalog/c/cusb232/ (¥600円)
- ワイヤー http://akizukidenshi.com/catalog/g/gP-03475/ (¥330円)
- キーボード、マウス、LCDモニタ、ケーブル類(お好きなもので、ヘッドレスで使う場合は不要です)
- インターネットに繋がる環境
- ホスト(PCやMac)、Raspberry Pi のセットアップやリモートからの操作で使います(このガイドではUbuntu 16.04を導入したPCを使っています)
1-1-2. OS(Raspbian)のセットアップ
RaspbberryPiをサポートしたOSはいくつかあります。
OS | Version | Kernel | TPM driver |
---|---|---|---|
Raspbian | June 2017 | 4.9.28-v7+ | 無し |
Ubunbtu Mate | 16.04.2 | 4.4 | (未確認) |
Snappy Ubuntu Core | 16.04.2 | 4.4 | (未確認) |
Windows IoT core | 有り |
ここでは最新のRaspbianを導入について簡単に手順を紹介します。ヘッドレス(LCD,KB無しを想定しています)
- Raspbian はDebian Jessieベースを利用するほうがトラブルが少ないです。 2017−8以降のRaspbianはDebian Stretchベースになっていますが、TPM,TSS関連のソフトウェアのビルドで色々ハマります。
- OSのSDイメージファイル(通常版,1.5GB)をダウンロード
- 念の為ハッシュ値を確認
- ダウンロードしたファイルをSDカードに書き込み
- SSHを有効化しておく(bootにsshファイル作成)
- SDカードをラズパイに挿し、ラズパイの電源投入
- SSH経由でログイン
- IPアドレス確認 (MACアドレスを控えておく)
- デフォルトのユーザ名:pi、パスワード:raspberry
- Updateしておく
- 自動更新にしておく
- パスワードを変更
- 勉強会に持参する場合はKBやLCDや有線LANが使えない場合が有りますのでシリアルコンソールの設定をしておきましょう
以下、実行コマンド例
$ sha1sum 2017-06-21-raspbian-jessie.zip
82a4ecfaadbef4cfb8625f673b5f7b91c24c8e32 2017-06-21-raspbian-jessie.zip
$ unzip 2017-06-21-raspbian-jessie.zip
$ sudo dd if=2017-06-21-raspbian-jessie.img of=/dev/mmcblk0 bs=4M
/media/SDPATH/にマウントされます(SDPATHはマウントされたSDカードのルートへのパス)。まず、SSHを有効化。
$ SDROOTPATH=/media/hoge/4DD6-9F24 (SDガードのマウントパス設定)
$ touch $SDROOTPATH/ssh
次に、シリアルコンソールを有効化。
$ sudo vi $SDROOTPATH/config.txt
I2Cを有効化
dtparam=i2c_arm=on
最後に下記を追加
dtoverlay=pi3-miniuart-bt
$ sudo vi $SDROOTPATH//cmdline.txt
最後の quiet splash plymouth.ignore-serial-consoles を削除
作成したSDカードをラズパイに挿入後、電源を接続して起動します。
1-1-3. シリアルコンソールでログイン
USB-UARTアダプタを接続し、ホストから下記でラズパイのシリアルコンソールに接続。
$ screen /dev/ttyUSB0 115200
初期IDは pi PWは raspberry です。
1-1-4. WIFIの設定
無線LAN環境の場合、シリアルコンソールでログイン後、下記ガイドにしたがってWIFIの設定を行います。
- SETTING WIFI UP VIA THE COMMAND LINE
1-1-5. SSHでリモートログイン
ラズパイがDHCPで取得したIPアドレスを検査
$ nmap -p22 192.168.0.1/24 (アドレスレンジは自身のネットワーク環境にあわせてください)
$ arp -na | grep -i b8:27:eb
RPIのIPアドレス発見できたら(以下の例では192.168.0.6)、SSHでリモート接続。
$ ssh -l pi 192.168.0.6
ログイン(PWはraspberry)できたら、アップデートを実施し最新状態にしておく。
$ sudo apt-get update
$ sudo apt-get -y dist-upgrade
$ sudo apt-get -y autoremove
$ sudo apt-get autoclean
自動更新にしておく(OPTION)。
$ sudo apt-get install -y unattended-upgrades
$ sudo vi /etc/apt/apt.conf.d/02periodic
次の二行追加し保存
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
$ sudo vi /etc/apt/apt.conf.d/50unattended-upgrades
次の一行のコメント削除
// "o=Raspbian,a=stable"
最後にデフォルトのパスワードを変更しておく
$ passwd
以上でラズパイの基本的な設定は完了です。
2. TPMおよびそのサポートの追加
Raspberry Piは標準ではTPMをサポートしていません。そのためソフトウェアのTPMエミュレータを使うか、TPMチップを追加して使うかの2つの方法が有ります。TPMには2つのバージョンがあります。1.2は古いTPMで暗号はRSAとSHA1しかサポートしません。2.0は新しいTPMで様々な暗号をサポートしています。残念ながら1.2と2.0には互換性がありません。新規に使うのであれば2.0が良いでしょう。 (サイトがドイツ語のみですが)p-letstrustのTPMボードは比較的安価で日本円で送料込み3000円位で入手可能です。
TPM | Type | FW Version | URL |
---|---|---|---|
Software TPM | SW(1.2) | http://ibmswtpm.sourceforge.net/ | |
tpm-emulator | SW(1.2) | https://github.com/PeterHuewe/tpm-emulator | |
IBM's Software TPM 2.0 | SW(2.0) | https://sourceforge.net/projects/ibmswtpm2/ | |
TPM 2.0 Simulator | SW(2.0) | https://github.com/stwagnr/tpm2simulator | |
Iridium 9645 | HW(1.2 I2C) | https://www.ehitex.de/en/evaluation-boards/infineon/2562/iridium-9645-tpm1.2-i2c?c=99 | |
Iridium 9670 | HW(1.2 SPI) | https://www.ehitex.de/en/evaluation-boards/infineon/2563/iridium-9670-tpm1.2-spi?c=99 | |
Iridium 9670 | HW(2.0 SPI) | https://www.ehitex.de/en/evaluation-boards/infineon/2564/iridium-9670-tpm2.0-spi | |
p-letstrust | HW(2.0 SPI) | https://buyzero.de/products/letstrust-hardware-tpm-trusted-platform-module | |
ST micro | HW(2.0 SPI) | N/A | |
TCG JRF版 | HW(2.0 I2C) |
2-1. TPMエミュレーターの使用(IBM版)
TPMチップが無い場合は TPMエミュレーターを使えます。まず、ソースコードをダウンロード。
$ mkdir -p sandbox/ibmswtpm2
$ cd sandbox/ibmswtpm2
$ wget -c http://downloads.sourceforge.net/project/ibmswtpm2/ibmtpm974.tar.gz
$ tar -zxvf ibmtpm974.tar.gz
$ cd src
ラズパイのLinux は 32Bit ですので Implementation.h の RADIX_BIT 定義を64から32に修正します。
#ifdef TPM_POSIX
#define RADIX_BITS 32
ビルドに必要な libssl-dev をInstallしておきます(RaspbianがDebian Jessieベースの場合)。
$ sudo apt-get install -y libssl-dev
RaspbianがDebian Stretchベース(2017-8以降)の場合は、 libssl1.1ではビルドがエラーになるため下記で
$ sudo apt-get install libssl1.0-dev
ビルドします。
$ make
tpm_serverが出来ますので、/sbinにインストールし起動します。標準のポート番号は 2321 です。
$ sudo cp tpm_server /sbin/
$ $ tpm_server > /dev/null 2>&1 &
[1] 3447
2-2. TPM2.0 搭載拡張ボードの使用
ここでは下記の2つのボードに対応する設定手順を示します。
- Infineon 社の Iridium 9670 (もしくは p-letstrust)は一般に入手が可能なラズパイ用TPMボードです。ラズパイとのインターフェースはSPIになります。
- TCG JRF配布版は Novoton 社のTPMを搭載したラズパイ用TPMボードで、ラズパイとのインターフェースはI2Cになります。これはTCG JRFとインサイトインターナショナル社による限定配布になりますので一般での入手はできません。
その他にもTPM2.0搭載のボードがございましたらご連絡いただけると助かります。
2-2-1. Linuxカーネルのリコンパイル。
標準カーネルはTPMデバイスをサポートしていないため、カーネルの再構築が必要になります。まず、カーネル再構築などに必要なパッケージを導入します。カーネルのコンパイルには時間がかかりますので、強制アクセス機能などもONにします。下記の例では組み込みで使いやすい TOMOYO Linux を有効にします。
$ sudo apt-get install bc
$ sudo apt-get install libncurses5-dev
$ sudo apt-get install i2c-tools
次に、ラズパイ用の最新カーネルをGithubから取得
$ git clone --depth=1 https://github.com/raspberrypi/linux
時間がかかるので、ちょっと休憩。次にRaspberryPi3用にカーネルをコンパイルします。
まず、カーネルコンフィグを修正しTPMを組み込みます。
$ cd linux
$ KERNEL=kernel7
$ make bcm2709_defconfig
標準設定ではTPMドライバ含め、セキュリティ関連機能がほとんど含まれないため追加します。
$ make menuconfig
- Device Driver
- Character devices
- TPM Hardware Support Y
- さらに TPM interface... すべて M に
- TPM Hardware Support Y
- Character devices
カーネルのダイナミックデバッグも有効にしておくとTPMが期待通りに動かない時のデバッグに役立ちます。 (OPTION)
- Kernel hacking
- printk and dmesg options
- Enable dynamic printk() support)
- printk and dmesg options
TOMOYO Linux の有効化 (OPTION)
- General setup
- Auditing support
- Security options
- Enable different security models
- TOMOYO Linux Support
更新された .config ファイルでTPMが有効化されているか確認
CONFIG_HW_RANDOM_TPM=y
# CONFIG_R3964 is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_CORE=m
CONFIG_TCG_TIS_SPI=m
CONFIG_TCG_TIS_I2C_ATMEL=m
CONFIG_TCG_TIS_I2C_INFINEON=m
CONFIG_TCG_TIS_I2C_NUVOTON=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_VTPM_PROXY=m
CONFIG_TCG_TIS_ST33ZP24=m
CONFIG_TCG_TIS_ST33ZP24_I2C=m
CONFIG_TCG_TIS_ST33ZP24_SPI=m
コンパイル開始。この間CPUがかなり熱くなりますので冷却ファンをつけたほうがよいです。
time make -j4 zImage modules dtbs
しばし休憩(終了まで1−2時間かかります)。無事終了したらインストール
$ sudo make modules_install
$ sudo cp arch/arm/boot/dts/*.dtb /boot/
$ sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
$ sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
$ sudo cp arch/arm/boot/zImage /boot/kernel7.img
ラズパイ再起動
$ sudo reboot
再度ログインしてカーネルが新しくなっていることを確認
$ uname-r
4.9.35-v7+
以上でTPM等を有効化したカーネルへの差し替えが完了しました。
2-2-2. TPMのデバイスツリーの追加
最新のTPMドライバーはデバイスツリー情報を元にドライバーの初期化を行います。
ここでは、TPMのデバイスツリー情報をデバイスツリーのオーバーレイの形でシステムに追加します。
2-2-2-1. Infineon(SPI)の場合は letstrust がDTSを提供しているのでそれをそのまま利用します。
wget http://letstrust.de/uploads/letstrust-tpm-overlay.dts
dtc -@ -I dts -O dtb -o letstrust-tpm-overlay.dtb letstrust-tpm-overlay.dts
sudo cp letstrust-tpm-overlay.dtb /boot/overlays/
config.txtを修正、再起動
$ sudo vi /boot/config.txt
dtoverlay=letstrust-tpm (を最後に追記)
TPMドライバを組み込みます
$ sudo modprobe tpm_tis_spi
$ dmesg | tail
[ 78.007599] tpm_tis_spi spi0.1: 2.0 TPM (device-id 0x1B, rev-id 16)
[ 78.097473] tpm tpm0: A TPM error (256) occurred continue selftest
2-2-2-2. Nuvoton(I2C)の場合は i2c-nuvoton.dts を作成し
// Overlay for tpm_i2c_nuvoton.
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2708";
fragment@0 {
target = <&i2c_arm>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
tpm_i2c_nuvoton: tpm@57 {
compatible = "nuvoton,npct650", "nuvoton,npct601";
reg = <0x57>;
label = "tpm";
linux,sml-base = <0x7f 0xfd450000>;
linux,sml-size = <0x10000>;
status = "okay";
};
};
};
};
コンパイルして配置、再起動
$ dtc -@ -I dts -O dtb -o i2c-nuvoton.dtb i2c-nuvoton.dts
$ sudo cp i2c-nuvoton.dtb /boot/overlays/
$ sudo vi /boot/config.txt
dtoverlay=i2c-nuvoton (を最後に追記)
$ sudo reboot
2-2-3. TPMデバイスドライバの組み込み
2-2-3−1. Infineon TPM (SPI) の場合
Linux標準のSPIドライバーで動作します。
$ sudo modprobe tpm_tis_spi
2-2-3−2. Nuvoton TPM (I2C) の場合
Nuvoton用のI2Cドライバーは正しく動作しない可能性があります。
$ sudo modprobe tpm_i2c_nuvoton
注意) NPCT650は現在のLinuxのデバイスドライバ(4.12の最新版含む)では動きません。(ただ、SMBIOS APIを使っているReadとWriteの部分の
tpm_i2c_infineon にならって素にI2Cを叩き遅延を挟む形に書きなおせば動くようです)
ひとまず、I2Cバスに接続したTPMを認識することはできます(出ない時は何回かコマンドを実行すると出てきます)。
$ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
0x57がNuvotonのTPMになります。
2-3. TSSのセットアップ
TPM2.0に対応したTSS(TCG Software Stack、TPMを使うためにライブラリ)はいくつかの種類があります。
URL | コメント | |
---|---|---|
IntelのTSS2.0 | https://github.com/01org/TPM2.0-TSS | TCGの仕様に準拠したTSS2.0 |
IBMのTSS2.0 | https://sourceforge.net/projects/ibmtpm20tss/ | 上記よりも軽い実装 |
MicrosoftのTSS | https://github.com/Microsoft/TSS.MSR | Windows用 |
GoogleのTSS | https://chromium.googlesource.com/chromiumos/third_party/tpm2/ | ? |
ここではTSSを用いてTPMの動作確認を行います。
TSSの使用の詳細については LinuxでTPM2.0を使う を参照してください。
2-3-1. IBM TSSのセットアップ
ビルドに必要なパッケージを導入
$ sudo apt-get install -y libssl-dev
最新のソースコードを https://sourceforge.net/projects/ibmtpm20tss/ からダウンロード(2017年8月では1045が最新ですが、APIに変更が有り別のAttestationデモと不整合となるため、しばらくは996を使うのが無難です)。
$ mkdir -p sandbox/ibmtss
$ cd sandbox/ibmtss
$ wget https://sourceforge.net/projects/ibmtpm20tss/files/ibmtss996.tar.gz
$ tar xvfz ibmtss996.tar.gz
$ cd utils
$ make
SWTPMの場合のおまじない (TPMが初期化されていないため下記を実行)
$ export TPM_INTERFACE_TYPE=socsim
$ ./powerup
$ ./startup
TPMチップのおまじない (TPM_INTERFACE_TYPEをdevにして、/tpm/tpm0のアクセス権を修正)
$ export TPM_INTERFACE_TYPE=dev
$ sudo chmod a+rwx /dev/tpm0
動作確認(TPMのCapabilityの確認)
$ ./getcapability -cap 6
moreData: 1
63 properties
TPM_PT 00000100 value 322e3000 TPM_PT_FAMILY_INDICATOR - a 4-octet character string containing the TPM Family value (TPM_SPEC_FAMILY)
TPM_PT 00000101 value 00000000 TPM_PT_LEVEL - the level of the specification
<snip>
TPM_PT 00000210 value 00001c20 TPM_PT_LOCKOUT_INTERVAL - the number of seconds before the value reported by TPM_PT_LOCKOUT_COUNTER is decremented
TPM_PT 00000211 value 00015180 TPM_PT_LOCKOUT_RECOVERY - the number of seconds after a lockoutAuth failure before use of lockoutAuth may be attempted again
TPM_PT 00000213 value 00000000 TPM_PT_AUDIT_COUNTER_0 - the high-order 32 bits of the command audit counter
動作確認(PCRの書き込みと読み出し)
$ ./pcrextend -ha 10 -ic ddddd
$ ./pcrread -ha 10
count 1
digest length 32
94 51 0c 61 2e 79 ce d7 07 51 3d 2b c6 99 3a 7f
09 f3 0b 98 44 95 4b 9e 2d ab ed 0b 36 86 62 c1
以上で、ラズパイでTPMを使えるようになりました。
2-3-2. Intel TSSのセットアップ (TBD)
今後 TPMの Resource Manager がKernelに取り組まれる予定です。そのため現時点ではKernelとTSSの組み合わせがよくわからない。大手のLinuxディストロが対応してから触るのが無難でしょう。
3. その他
3-1. 注意点
- ラズパイは便利ですが、起動コードが対応しないため、ラズパイを使ってTrusted Bootは実装できません。
- 各社(Infineon,Novoton,STmicro, Atmel, NationZ)からTPMチップは出ていますが、パッケージやPIN配置に互換性がありません。製品での利用につては別途詳細についてTPMベンダーに問い合わせてください。
3-2. Trusted Boot/Secure Boot
ラズパイでは出来ないのですが、現状をまとめておきます。基本的にはBroadcomのIPLがブラックボックスのためラズパイを使って真のTrusted Bootは実装できません。 ただし、u-bootがTPM2.0に対応すれば開発環境としては色々できるようになると思います。
- GPU側ブートローダー (SoCのROM)
- ラズパイは最初にGPUが起動するが、実装は非公開でありこの部分をTPM対応にすることは出来ない。したがってラズパイでCRTMの実装ができない。
- bootcode.bin (microSD)
- ARMのL2で実行、start.elfを実行
- loader.bin (microSD)
- RAM上で実行
- start.elf (microSD)
- RAM上で実行、 Linuxの読み込み
- u-boot
- TPM1.2はサポートしていますが、2.0のサポートはまだのようです。2.0がサポートされれば、Linuxの起動をU-Bootに行わせることで、Linux Kernelの計測や、MACのポリシーの計測が可能になると思います。
- Linux
- デバイスドライバーはTPM2.0に対応しています。
- IMAを使う場合は、IMAの初期化前にTPMが浸かるようになっている必要があります。I2CのやSPIのドライバの初期化のタイミングについて注意が必要です。
4. 参照
- Raspberry pi
- TPM 2.0 の仕様
- Emulation of TPM on Raspberry Pi
- Howto Enable TPM Support on a Raspberry PI (0, 0W, 1, 2, 3) and make it work with the LetsTrust TPM
- TPM on Windows 10 IoT Core
- Security architecture and implementation for a TPM-based mobile authentication device, 2013