はじめに
Yocto ProjectでもいくつかのレイヤでTPMをサポートしている。
ラズベリーパイシリーズはTPMモジュールは搭載されておらず、外付けのモジュールを使用するか
エミュレータを使用する必要がある。
meta-security配下にあるmeta-tpm
ではTPMエミュレータを使用することができる。
今回はmeta-tpmにあるエミュレータを使用してTPM2.0の機能を使ってみる。
run_crops.sh
今回も前回作成したrun_crops.shを使用する。
cmd="source $(pwd)/poky/oe-init-build-env"
if [ $# -gt 0 ] ; then
cmd="${cmd} && $@"
fi
docker run --rm -it -v $(pwd):$(pwd) crops/poky --workdir=$(pwd) bash -c "${cmd}"
実行権限をつけてPATHの通ったところに置いておく。
$ chmod +x ./run_crops.sh
今回は前回まで/workdir
だった部分を$(pwd)
にして、ホストとコンテナ内のパスが完全に一致するようにしてみた。
Pokyの作成
作業場所は~/work/yocto/rpi_honister
とする。
$ mkdir -p ~/work/yocto/rpi_honister && cd ~/work/yocto/rpi_honister
Pokyの取得
まずはPoky一式を取得する。
$ git clone git://git.yoctoproject.org/poky.git -b honister
meta-raspberrypiの取得
meta-raspberrypiをbitbake-layers layerindex-fetch
で取得する。
$ run_crops.sh bitbake-layers layerindex-fetch meta-raspberrypi
meta-securityの取得
meta-securityはいくつかのレイヤに依存しているので下記の手順で取得する。
$ run_crops.sh bitbake-layers layerindex-fetch meta-oe
$ run_crops.sh bitbake-layers layerindex-fetch meta-python
$ run_crops.sh bitbake-layers layerindex-fetch meta-networking
$ run_crops.sh bitbake-layers layerindex-fetch meta-perl
$ run_crops.sh bitbake-layers layerindex-fetch meta-security
meta-tpmをビルド対象に追加
meta-securityのサブレイヤとして定義されているmeta-tpmはlayerindex-fetchできないので、add-layerする。
$ run_crops.sh bitbake-layers add-layer ../poky/meta-security/meta-tpm
レイヤの確認
$ run_crops.sh bitbake-layers show-layers
### Shell environment set up for builds. ###
You can now run 'bitbake <target>'
Common targets are:
core-image-minimal
core-image-full-cmdline
core-image-sato
core-image-weston
meta-toolchain
meta-ide-support
You can also run generated qemu images with a command like 'runqemu qemux86'
Other commonly useful commands are:
- 'devtool' and 'recipetool' handle common recipe tasks
- 'bitbake-layers' handles common layer tasks
- 'oe-pkgdata-util' handles common target package tasks
NOTE: Starting bitbake server...
layer path priority
==========================================================================
meta /home/mickey/work/yocto/rpi_honister/poky/meta 5
meta-poky /home/mickey/work/yocto/rpi_honister/poky/meta-poky 5
meta-yocto-bsp /home/mickey/work/yocto/rpi_honister/poky/meta-yocto-bsp 5
meta-raspberrypi /home/mickey/work/yocto/rpi_honister/poky/meta-raspberrypi 9
meta-oe /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-oe 6
meta-python /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-python 7
meta-networking /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-networking 5
meta-perl /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-perl 6
meta-security /home/mickey/work/yocto/rpi_honister/poky/meta-security 8
meta-tpm /home/mickey/work/yocto/rpi_honister/poky/meta-security/meta-tpm 10
local.confの修正
build/conf/local.conf
に下記の内容を追加する。
MACHINE = "raspberrypi4-64"
DL_DIR ?= "${TOPDIR}/../downloads"
ENABLE_UART = "1"
DISTRO_FEATURES:append = " systemd pam"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""
IMAGE_INSTALL:append = " connman \
connman-client \
"
DISTRO_FEATURES:append = " security tpm2"
ビルド
TPM2.0を使いたいのでsecurity-tpm2-image
をビルドする。
$ run_crops.sh bitbake security-tpm2-image
SDに書き込み
./build/tmp/deploy/images/raspberrypi4-64/security-tpm2-image-raspberrypi4-64.wic.bz2
が書き込み用イメージとなる。
これをbmaptoolでマイクロSDカードに書き込む。
$ sudo bmaptool copy ./build/tmp/deploy/images/raspberrypi4-64/security-tpm2-image-raspberrypi4-64.wic.bz2 /dev/sdX
/dev/sdX
は適宜読み替え。
security-tpm2-image
にはibmswtpm2
というTPMエミュレータが組み込まれている。
ibmswtpm2を使用してtpm2-toolsを実行するための情報はあまり多くない。
Setup Virtual TPMというところに欲しかった情報がまとまっていたので参考にする。
security-tpm2-imageで起動した状態からibmswtpm2を使用するためには以下の手順が必要になる。
- tpm_serverの起動
- tpm2-abrmdの起動
tpm_serverがibmswtpm2が提供するユーザーランドのインターフェースとなる。
tpm2-abrmdはTPM2 Access Broker & Resource Manager Daemon
の略で、
tpm2-toolsのコマンドはこのデーモンを介してTPM2.0の機能にアクセスする。
なので、今回のケースではtpm2-abrmdがtpm_serverのクライアントとして接続される必要がある。
試しに、これらの手順を実施しない状態でtpm2_clear
を実行してみる。
# tpm2_clear
** (process:330): CRITICAL **: 17:20:50.253: failed to allocate dbus proxy object: Error calling StartServiceByName for com.intel.tss2.Tabrmd: Timeout was reached
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:79:tcti_from_init() TCTI init for function 0x7fb856c280 failed with a0008
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:109:tcti_from_info() Could not initialize TCTI named: tcti-abrmd
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr-dl.c:154:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-tabrmd.so.0
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tcti-device.c:440:Tss2_Tcti_Device_Init() Failed to open specified TCTI device file /dev/tpmrm0: No such file or directory
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:79:tcti_from_init() TCTI init for function 0x7fb6fbd590 failed with a000a
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:109:tcti_from_info() Could not initialize TCTI named: tcti-device
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr-dl.c:154:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-device.so.0
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tcti-device.c:440:Tss2_Tcti_Device_Init() Failed to open specified TCTI device file /dev/tpm0: No such file or directory
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:79:tcti_from_init() TCTI init for function 0x7fb6fbd590 failed with a000a
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:109:tcti_from_info() Could not initialize TCTI named: tcti-device
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr-dl.c:154:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-device.so.0
WARNING:tcti:../tpm2-tss-3.0.3/src/util/io.c:252:socket_connect() Failed to connect to host 127.0.0.1, port 2321: errno 111: Connection refused
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tcti-swtpm.c:592:Tss2_Tcti_Swtpm_Init() Cannot connect to swtpm TPM socket
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:79:tcti_from_init() TCTI init for function 0x7fb6fbd9e0 failed with a000a
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:109:tcti_from_info() Could not initialize TCTI named: tcti-swtpm
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr-dl.c:154:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-swtpm.so.0
WARNING:tcti:../tpm2-tss-3.0.3/src/util/io.c:252:socket_connect() Failed to connect to host 127.0.0.1, port 2321: errno 111: Connection refused
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:79:tcti_from_init() TCTI init for function 0x7fb6fbd9b0 failed with a000a
WARNING:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:109:tcti_from_info() Could not initialize TCTI named: tcti-socket
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr-dl.c:154:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-mssim.so.0
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr-dl.c:254:tctildr_get_default() No standard TCTI could be loaded
ERROR:tcti:../tpm2-tss-3.0.3/src/tss2-tcti/tctildr.c:416:Tss2_TctiLdr_Initialize_Ex() Failed to instantiate TCTI
ERROR: Could not load tcti, got: "(null)"
このようにエラーとなる。
tpm_serverの起動
単純にデーモンとして起動する。
# tpm_server &
LIBRARY_COMPATIBILITY_CHECK is ON
Manufacturing NV state...
Size of OBJECT = 2600
Size of components in TPMT_SENSITIVE = 1096
TPMI_ALG_PUBLIC 2
TPM2B_AUTH 66
TPM2B_DIGEST 66
TPMU_SENSITIVE_COMPOSITE 962
Starting ACT thread...
TPM command server listening on port 2321
Platform server listening on port 2322
tpm2-abrmdは2321のポートに接続する必要がある。
tpm2-abrmdの起動
本来はsystemdのサービスとして起動できるが、提供されているtpm2-abrmd.serviceは、エミュレータではなく物理デバイスを使用した場合の設定が記述されているので、とりあえず手動で起動する。
# tpm2-abrmd --tcti=mssim:host=localhost,port=2321 --allow-root &
tpm2-toolsの使用
とりあえず、tpm2_clearを実行してみる。
# tpm2_clear
これでエラーが発生しなければTPM2.0は使えてるはず。
試しにtpm2_createakのEXAMPLES]を実行してみる。
# tpm2_createek -c ek.handle -G rsa -u ek.pub
# tpm2_createak -C ek.handle -c ak.ctx -u ak.pub -n ak.name
# tpm2_evictcontrol -C o -c ak.ctx 0x81010002
# ls
ak.ctx ak.name ak.pub ek.handle ek.pub
これらのコマンドでエラーが発生せず、上記の5つのファイルが作成されていれば問題ない。
サービス化
ここまでで以下の手順を実施することでTPM2.0エミュレータが使用できることが確認できた。
- tpm_serverの起動
- tpm2-abrmdの起動
これらをsystemdのサービスとして実行できるようにする。
tpm_serverのサービス化
/etc/systemd/system/tpm-server.service
を以下の内容で作成する。
[Unit]
Description=IBM's Software TPM2.0 server
[Service]
ExecStart=/usr/bin/tpm_server
Restart=on-failure
Type=simple
[Install]
WantedBy=multi-user.target
サービスを起動する。
# systemctl start tpm-server
systemctl statusで起動できていることを確認する。
# systemctl status tpm-server
* tpm-server.service - IBM Software TPM2.0 Emulater server
Loaded: loaded (8;;file://raspberrypi4-64/etc/systemd/system/tpm-server.service/etc/systemd/system/tpm-server.service8;;; disabled; vendor preset: disabled)
Active: active (running) since Fri 2021-11-19 17:30:26 UTC; 9s ago
Main PID: 362 (tpm_server)
Tasks: 3 (limit: 4163)
CGroup: /system.slice/tpm-server.service
`-362 /usr/bin/tpm_server
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: Manufacturing NV state...
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: Size of OBJECT = 2600
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: Size of components in TPMT_SENSITIVE = 1096
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: TPMI_ALG_PUBLIC 2
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: TPM2B_AUTH 66
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: TPM2B_DIGEST 66
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: TPMU_SENSITIVE_COMPOSITE 962
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: Starting ACT thread...
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: TPM command server listening on port 2321
Nov 19 17:30:26 raspberrypi4-64 tpm_server[362]: Platform server listening on port 2322
次回起動時のためにenableしておく。
# systemctl enable tpm-server
tpm2_abrmd.serviceの修正
/lib/systemd/system/tpm2-abrmd.service
を以下の内容に修正する。
[Unit]
Description=TPM2 Access Broker and Resource Management Daemon
After=tpm-server.service
Requires=tpm-server.service
[Service]
Type=dbus
BusName=com.intel.tss2.Tabrmd
ExecStart=/usr/sbin/tpm2-abrmd --tcti=mssim:host=localhost,port=2321
User=tss
[Install]
WantedBy=multi-user.target
User=tss
しているのでExecStart行では--allow-root
は不要となる。
変更後のユニットファイルをリロードする。
# systemctl daemon-reload
サービスを起動する。
# systemctl start tpm2-abrmd
systemctl statusで起動できていることを確認する。
# systemctl status tpm2-abrmd
* tpm2-abrmd.service - TPM2 Access Broker and Resource Management Daemon
Loaded: loaded (8;;file://raspberrypi4-64/lib/systemd/system/tpm2-abrmd.service/lib/systemd/system/tpm2-abrmd.service8;;; disabled; vendor preset: disabled)
Active: active (running) since Fri 2021-11-19 17:39:30 UTC; 1min 17s ago
Main PID: 409 (tpm2-abrmd)
Tasks: 6 (limit: 4163)
CGroup: /system.slice/tpm2-abrmd.service
`-409 /usr/sbin/tpm2-abrmd --tcti=mssim:host=localhost,port=2321
Nov 19 17:39:30 raspberrypi4-64 systemd[1]: Starting TPM2 Access Broker and Resource Management Daemon...
Nov 19 17:39:30 raspberrypi4-64 tpm2-abrmd[409]: tcti_conf before: "(null)"
Nov 19 17:39:30 raspberrypi4-64 tpm2-abrmd[409]: tcti_conf after: "mssim:host=localhost,port=2321"
Nov 19 17:39:30 raspberrypi4-64 systemd[1]: Started TPM2 Access Broker and Resource Management Daemon.
こちらも次回起動時のためにenableしておく。
# systemctl enable tpm2-abrmd
再起動して動作確認
ラズベリーパイをリブートしてtpm2_clearを実行してみる。
# tpm2_clear
これでエラーが出なければ成功。
レシピに組み込む
これまでラズベリーパイ上で行ってきた変更の内容をレシピに組み込む。
meta-vtpm2-helperの作成
$ run_crops.sh bitbake-layers create-layer -p 20 meta-vtpm2-helper
$ mv build/meta-vtpm2-helper poky
$ run_crops.sh bitbake-layers add-layer ../poky/meta-vtpm2-helper
bitbake-layers show-layersで次のようになっていることを確認する。
$ run_crops.sh bitbake-layers show-layers
...(snip)...
layer path priority
==========================================================================
meta /home/mickey/work/yocto/rpi_honister/poky/meta 5
meta-poky /home/mickey/work/yocto/rpi_honister/poky/meta-poky 5
meta-yocto-bsp /home/mickey/work/yocto/rpi_honister/poky/meta-yocto-bsp 5
meta-raspberrypi /home/mickey/work/yocto/rpi_honister/poky/meta-raspberrypi 9
meta-oe /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-oe 6
meta-python /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-python 7
meta-networking /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-networking 5
meta-perl /home/mickey/work/yocto/rpi_honister/poky/meta-openembedded/meta-perl 6
meta-security /home/mickey/work/yocto/rpi_honister/poky/meta-security 8
meta-tpm /home/mickey/work/yocto/rpi_honister/poky/meta-security/meta-tpm 10
meta-vtpm2-helper /home/mickey/work/yocto/rpi_honister/poky/meta-vtpm2-helper 20
tpm2-abrmdのbbappendの作成
パッチファイルの作成
~/work/yocto/rpi_honister/tpm2-abrmd.service.in.patch
を以下の内容で作成する。
diff --git a/dist/tpm2-abrmd.service.in b/dist/tpm2-abrmd.service.in
index b0b562c..2252d93 100644
--- a/dist/tpm2-abrmd.service.in
+++ b/dist/tpm2-abrmd.service.in
@@ -2,13 +2,13 @@
Description=TPM2 Access Broker and Resource Management Daemon
# These settings are needed when using the device TCTI. If the
# TCP mssim is used then the settings should be commented out.
-After=dev-tpm0.device
-Requires=dev-tpm0.device
+After=tpm-server.service
+Requires=tpm-server.service
[Service]
Type=dbus
BusName=com.intel.tss2.Tabrmd
-ExecStart=@SBINDIR@/tpm2-abrmd
+ExecStart=/usr/sbin/tpm2-abrmd --tcti=mssim:host=localhost,port=2321
User=tss
[Install]
bbappendの作成
recipetoolを使用して、作成したパッチを登録する。
$ run_crops.sh recipetool appendsrcfile ../poky/meta-vtpm2-helper tpm2-abrmd ~/work/yocto/rpi_honister/tpm2-abrmd.service.in.patch
bbappendの修正
tpm2-abrmdのレシピではサービスがdisableになっているため、これをenableにするために、
~/work/yocto/rpi_honister/poky/meta-vtpm2-helper/recipes-tpm2/tpm2-abrmd/tpm2-abrmd_2.4.0.bbappend
を以下の内容に修正する。
SRC_URI += "file://tpm2-abrmd.service.in.patch;subdir=git"
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SYSTEMD_AUTO_ENABLE:${PN} = "enable"
ibmswtpm2のbbappendの作成
tpm-server.serviceの作成
~/work/yocto/rpi_honister/tpm-server.service
を以下の内容で作成する。
[Unit]
Description=IBM's Software TPM2.0 server
[Service]
ExecStart=/usr/bin/tpm_server
Restart=on-failure
Type=simple
[Install]
WantedBy=multi-user.target
bbappendの作成
recipetoolを使用して、作成したユニットファイルを登録する。
$ run_crops.sh recipetool appendsrcfile ../poky/meta-vtpm2-helper ibmswtpm2 ~/work/yocto/rpi_honister/tpm-server.service
bbappendの修正
追加したユニットファイルをsystemdのサービスとして登録するために、
~/work/yocto/rpi_honister/poky/meta-vtpm2-helper/recipes-tpm2/ibmswtpm2/ibmswtpm2_1661.bbappend
を以下の内容に修正する。
SRC_URI += "file://tpm-server.service;subdir=src"
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SYSTEMD_PACKAGES += "${PN}"
SYSTEMD_SERVICE:${PN} = "tpm-server.service"
SYSTEMD_AUTO_ENABLE:${PN} = "enable"
do_install:append() {
install -d ${D}${systemd_unitdir}/system
install -m 0644 ${S}/tpm-server.service ${D}${systemd_unitdir}/system
}
FILES:${PN} += "${systemd_unitdir}/system/tpm-server.service"
イメージの再作成、動作確認
$ run_crops.sh bitbake security-tpm2-image
作成されたイメージを書き込んだマイクロSDカードでラズベリーパイ4を起動して、tpm_clearなどを実行してエラーが発生しないことを確認する。
起動直後にtpm-server.serviceとtpm2-abrmd.serviceの状態を確認すると下記のようになった。
# systemctl status tpm-server
* tpm-server.service - IBM's Software TPM2.0 server
Loaded: loaded (8;;file://raspberrypi4-64/lib/systemd/system/tpm-server.service/lib/systemd/system/tpm-server.service8;;; disabled; vendor preset: disabled)
Active: active (running) since Fri 2021-11-19 17:19:33 UTC; 20s ago
Main PID: 278 (tpm_server)
Tasks: 3 (limit: 4163)
CGroup: /system.slice/tpm-server.service
`-278 /usr/bin/tpm_server
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: Size of components in TPMT_SENSITIVE = 1096
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: TPMI_ALG_PUBLIC 2
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: TPM2B_AUTH 66
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: TPM2B_DIGEST 66
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: TPMU_SENSITIVE_COMPOSITE 962
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: Starting ACT thread...
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: TPM command server listening on port 2321
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: Platform server listening on port 2322
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: Command IPv6 client accepted
Nov 19 17:19:33 raspberrypi4-64 tpm_server[278]: Platform IPv6 client accepted
# systemctl status tpm2-abrmd
* tpm2-abrmd.service - TPM2 Access Broker and Resource Management Daemon
Loaded: loaded (8;;file://raspberrypi4-64/lib/systemd/system/tpm2-abrmd.service/lib/systemd/system/tpm2-abrmd.service8;;; enabled; vendor preset: enabled)
Active: active (running) since Fri 2021-11-19 17:19:33 UTC; 28s ago
Main PID: 280 (tpm2-abrmd)
Tasks: 6 (limit: 4163)
CGroup: /system.slice/tpm2-abrmd.service
`-280 /usr/sbin/tpm2-abrmd --tcti=mssim:host=localhost,port=2321
Nov 19 17:19:33 raspberrypi4-64 systemd[1]: Starting TPM2 Access Broker and Resource Management Daemon...
Nov 19 17:19:33 raspberrypi4-64 tpm2-abrmd[280]: tcti_conf before: "(null)"
Nov 19 17:19:33 raspberrypi4-64 tpm2-abrmd[280]: tcti_conf after: "mssim:host=localhost,port=2321"
Nov 19 17:19:33 raspberrypi4-64 systemd[1]: Started TPM2 Access Broker and Resource Management Daemon.
意図通りの動作をしている。
まとめ
ラズベリーパイ4でTPM2.0エミュレータを動かした。
HONISTER向けのbbappendなども作ってみたが、だいたい問題なく作業できた。
あくまでもエミュレータなので、実際にラズベリーパイでTPM2.0を使う場合は、TPM2.0モジュールを使用する必要があるが、
TPM2.0を使用するソフトウェアの開発をモジュール無しでも行える環境を作成できることはわかった。
CROPSを使用しても、作業内容には大きな影響はない感じだった。