32
26

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 5 years have passed since last update.

Raspberry Pi でTPMを使う

Last updated at Posted at 2017-07-22

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を対象にしています)
  • Raspberry Pi 用電源(5V, 3A)
  • MicroSDカード (サイズは8GB以上、お好きなもので)
  • シリアル接続用のUSB-UARTアダプタ、接続ケーブル(3.3V対応であれば、お好きなもので)
  • キーボード、マウス、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の設定を行います。

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が期待通りに動かない時のデバッグに役立ちます。 (OPTION)

  • Kernel hacking
    • printk and dmesg options
      • Enable dynamic printk() support)

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. 参照

32
26
5

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
32
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?