LinuxでTPM2.0を使う

Linux上でTPM2.0を使う際の基本をまとめます。

PCの場合は大手の最新ディストロではTPM2.0をサポートしています。PC以外のPlatformでLinuxでTPM2.0を使えるようにするまでのセットアップは下記を参照してください。Linux KernelがTPMを認識したあとは、Server, PC,組み込みで大きな違いはありません。

- [Raspberry PI](http://qiita.com/mune10/items/5f565fcd8f010179d529)
- [Minnowboard MAX/Turbot (Atom,PTT)](http://qiita.com/mune10/items/bb6769fa857dc95b07fd)
- [OpenBlocks VX1 (Atom,PTT)](http://qiita.com/mune10/items/3898c61804dba3ed1a0c)
- NUC (6th gen, PTT) - TBD
- Dell XPS (6th gen, PTT) - TBD

注意

- PCの場合はBIOSがTPMを初期化済みです。それ以外のPlatformでBootloaderがTPMに対応していない場合は、TPMの初期化作業をOSサイドで行う必要が有ります。
- Raspbian はしばらくは Debian Jessie ベース（2017−0７-05）を使うのが無難です。下記のセットアップは Debian Stretch ベース（2017-08-16）ではで依存パッケージが変わったあためそのままではうまく動きません。

# 1. TSS2.0


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/ | ?

InteのTSS2.0はLinuxの主要ディストロでサポートされていますが、まだTCGの仕様も含めて開発途上のため問題も多く、ドキュメントも不足しています。
IBMのTSS2.0は軽量のTSSでリソースマネージャーはサポートしませんが、コマンドベースでTPMを使った基本的な操作を実行することが出来ます。

ここでは、Debian/Ubuntu上でIBMのTSS2.0のセットアップ方法と使い方についての解説します。

## 1-2. IBM TSSのセットアップ

必要なパッケージを導入します。、

    sudo apt-get install -y libssl-dev gawk

IBM TSS2.0は [sourceforge](https://sourceforge.net/projects/ibmtpm20tss/) で公開されています。最新の tar.gz ファイルをダウンロードしてビルドします。

    $ 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を使っている場合は

    $ export TPM_INTERFACE_TYPE=socsim
    $ ./powerup
    $ ./startup

/dev/tpm0のTPMチップを使う場合は

    $ export TPM_INTERFACE_TYPE=dev
    $ sudo chmod a+rwx /dev/tpm0

動作確認

    $ ./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[10]を更新してみます。

    $ ./pcrextend -ha 10 -ic ddddd
    Client accepted
    TPM command server listening on port 2321
    $ ./pcrread -ha 10
    Client accepted
    TPM command server listening on port 2321
    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 



デモが動くようにライブラリを/usr/libにインストールしておきます

    sudo cp libtss.so /usr/lib/
    sudo ln -s /usr/lib/libtss.so /usr/lib/libtss.so.0
    sudo ln -s /usr/lib/libtss.so /usr/lib/libtss.so.0.1


## 1-3. リグレッションテストの実行

utils ディレクトリから下記のコマンドを実行します。

    $ ./reg.sh -a
    ＜SNIP>
    Success - 31 Tests 0 Warnings

IBMのSWTPMは最新のTPM2.0実装のため、それに対応したIBMTSSのリグレッションテストをパスしますが、市販のTPMチップはスペックへの対応状態がまちまちのためエラーになります。その場合は面倒ですが、テストケースを修正しエラーとなるテストを削除します。以下にTPM2,0実装でエラーになるケースをまとめておきます（随時更新の予定）。

- ECCに未対応 => すべてのテストケースからECC関連のテストを削除
- SHA348に未対応 =>  すべてのテストケースからSHA348関連のテストを削除
- gettimeに未対応
- nvcertifyに未対応
- getcommandauditdigestに未対応
- policyticketに未対応


| No |           | SWTPM | Infineon (SPI) | Nuvoton (I2C) |
|----|-----------|-------|----------------|---------------|
|    | (initkey) | ok    | w/o ECC,SHA348 |  w/o ECC,SHA348  |
|  1 | Random    | pass  | pass           | pass  |
|  2 | PCR       | pass  |                | w/o SHA348|
|  3 | primary keys | pass
|  4 | createloaded - rev 138 | pass
|  5 | HMAC       | pass | pass | pass
|  6 | HMAC(bind) | pass | pass | FAIL
|  7 | HMAC(salt) | pass | w/o ECC,SHA348 |
|  8 | Hierarchy | pass | pass
|  9 | Storage | pass | w/o ECC,SHA348 |
| 10 | Object Change Auth | pass
| 11 | Encrypt and decrypt sessions | pass
| 12 | Sign | pass | FAIL
| 13 | NV | pass | FAIL
| 14 | NV PIN Index - rev 138 | pass
| 15 | Evict control | pass | pass | pass
| 16 | RSA encrypt decrypt | pass
| 17 | AES encrypt decrypt | pass
| 18 | AES encrypt decrypt - rev 138 | pass
| 19 | HMAC and Hash | pass | w/o SHA348|
| 20 | Attestation |pass | w/o ECC, sha348, gettime, nvcertify, getcommandauditdigest |  
| 21 | Policy | pass
| 22 | Policy - rev 138 |
| 23 | Context | pass | pass | pass
| 24 | Clocks and Timers | pass | pass | FAIL
| 25 | DA logic | pass | pass | FAIL
| 26 | Unseal | pass | pass | pass
| 27 | Duplication | pass | FAIL  | w/o SHA348
| 28 | ECC | pass
| 29 | Credential | pass | pass | pass

# 2. IBM TSS2.0のデモの実行

IBM TSS2.0はTPMにアクセスする個別のコマンドで構成されていますが、IBM TSS2.0のデモではこれをWeb経由でTPMを操作します。実行にはApacheとPHPが必要になりますので導入します。

    $ sudo apt-get update
    $ sudo apt-get install apache2 -y
    $ sudo apt-get install php5 libapache2-mod-php5 -y

次に デモをインストールします

    $ cd demo
    $ sudo mkdir /var/www/html/tpm2
    $ sudo make

hostname -I でホスト名を確認しWebブラウザでアクセスします（例 http://localhost/tpm2）

![Screenshot from 2017-08-12 06-13-35.png](https://qiita-image-store.s3.amazonaws.com/0/157475/7111c707-8124-c649-4e36-7b8a997ebd24.png)

PCRの値が一覧できます。

![Screenshot from 2017-08-12 06-21-53.png](https://qiita-image-store.s3.amazonaws.com/0/157475/d91247a2-cb82-80c8-5898-c0f6ed3b6458.png)

このデモは標準ではTPMエミュレーターをつかいます。物理TPMを用いる場合は

    $ sudo make -f makefile_dev

でインストールすれば、/dev/tpm0をアクセスするようになります。


# 3. IBM's TPM 2.0 Attestation Client Server

TPM2.0 をつかってリモートアテステーションをするサーバーとクライアントのデモが公開されています。

https://sourceforge.net/projects/ibmtpm20acs/

以下にRaspbianでの設定をまとめておきます。 詳細は README.txtファイルを参照してください。

## 3-1.  Webアプリのセットアップ

依存パッケージのインストール

    sudo apt-get -y install apache2
    sudo apt-get -y install libjson-c-dev
    sudo apt-get -y install libmysqlclient-dev
    sudo apt-get -y install php5 php5-dev php5-mysql
    sudo apt-get -y install mysql-server

JSONのインクルードパスの修正

    sudo ln -s /usr/include/json-c /usr/include/json

MySQLの設定

    sudo mysql
    mysql> create database tpm2;
    mysql> CREATE USER pi;
    mysql> grant all privileges on tpm2.* to 'pi'@'localhost';
    mysql> set password for 'pi'@'localhost' = '' ;



インストール先の作成

    sudo mkdir /var/www/html/acs
    sudo chown user /var/www/html/acs
    sudo chgrp user /var/www/html/acs
    sudo chmod 777  /var/www/html/acs

デモのダウンロードとビルド（TSSと同じディレクトリに展開します）

    cd ibmtpm20tss

    wget https://sourceforge.net/projects/ibmtpm20acs/files/ibmacs976.tar.gz
    tar xvfz ibmacs976.tar.gz
    cd acs
    sudo make

スキーマの読み込み

    mysql -D tpm2 < dbinit.sql

アパッチ再起動

    sudo service apache2 restart

ブラウザで http://HOSTNAME/acs/navigation.php にアクセスします。（HOSTNAMEはローカルであれば localhost、リモートであればIPアドレスかホスト名）

## 3-2. アテステーションサーバーの準備

EKのCA作成（Passwordはrrrr）

    openssl genrsa -out cakey.pem -aes256 -passout pass:rrrr 2048
    openssl req -new -x509 -key cakey.pem -out cacert.pem -days 3650
    cp cacert.pem ../utils/certificates/


../utils/certificates/rootcerts.txt のファイルのパスを環境に合わせて修正します。

サーバー起動

    export ACS_PORT=2323
    ./server -v -root ../utils/certificates/rootcerts.txt >! serverenroll.log4j

## 3-3. クライアントの登録

    ./clientenroll -alg rsa -v -ho localhost

失敗します。（調査中）


# 4. 関連情報

- SETTING UP AN APACHE WEB SERVER ON A RASPBERRY PI
    - https://www.raspberrypi.org/documentation/remote-access/web-server/apache.md）
- OpenSSLでTPM2.0を使う話
    - https://dguerriblog.wordpress.com/2016/03/03/tpm2-0-and-openssl-on-linux-2/