このドキュメントではQEMUとDockerコンテナを用いたOP-TEE Remote Attestation 実行環境の構築と、VERAISON Verification を活用した一連の動作を確認手順を説明します。 OP-TEEはRaspberry Pi 3B+ (Arm Cortex-A TrustZone)でも動作が確認できています。
下図はプロビジョニング(0)、リモートアテステーション(1)-(5)、セキュアコミュニケーション(6)の手順を示しています。

開発物を実行するには以下を満たす環境を準備する必要があります。
- Docker がインストールされていること
- Docker デーモンが稼働していること
- Docker 用に30-40GBのディスクが残っていること(
docker system dfで確認できる。容量が少なければdocker system prune --volumes --allで確保を勧める。) jqがインストールされていること(Ubuntu であれば、sudo apt-get install jq)
以下の 0 から 6 の手順に従い、リモートアテステーションの一連の流れをテストしてください。 i.MX8MP EVK 実機でのアテステーションは手順 8 を参照してください。
i.MX 8M Plus 向け Yocto ビルドと実機でのアテステーションは手順 8 を参照してください。i.MX 8M Plus は SD 先頭の imx-boot に埋め込まれた tee.bin を使用するため、ビルドスクリプトは imx-boot の再ビルドと WIC 再パッケージを行います。
最初にgit cloneによりoptee-raのソースを取り寄せます。
git clone https://github.com/iisec-suzaki/optee-ra
cd optee-raVeraisonのソースをgithubから取り寄せます。
git clone https://github.com/veraison/services.git
cd services && git checkout b50b67d && cd ..この際に下記のメッセージがでますが、問題ありません。
Note: switching to 'b50b67d'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at b50b67d Merge pull request #208 from aj-stein-nist/patch-1
次にホストマシン上で動作させるサービスを起動します。 以下のコマンドにより、Veraison を起動することができます。起動には時間がかかります。
make -C services docker-deployサービスを起動した後、以下のコマンドで、サービスの状態を確認することができます。zsh を使っている場合、source services/deployments/docker/env.bash の代わりに source services/deployments/docker/env.zsh を実行してください。
source services/deployments/docker/env.bash
veraison status正常に、Veraison のサービスが起動した場合、以下のような出力が得られます。
vts: running
provisioning: running
verification: running
management: running
keycloak: running以下のコマンドで、Verifier に対して、trust anchor と reference value を登録します。これらの値は Attester から送信された evidence の検証に用いられます。登録する値を変更したい場合は provisoning/data 以下のファイルを改変してください。
# QEMU (default)
./provisoning/run.sh qemu
# i.MX 8M Plus
./provisoning/run.sh imx引数を省略した場合は qemu が使われます。
登録された値は以下のコマンドで確認できます。
veraison stores登録が成功すると、以下のような出力が得られます。これは Verifier に登録された値を示しています。
TRUST ANCHORS:
--------------
{
"scheme": "PSA_IOT",
"type": "trust anchor",
"subType": "",
"attributes": {
"PSA_IOT.hw-model": "RoadRunner",
"PSA_IOT.hw-vendor": "ACME",
"PSA_IOT.iak-pub": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMKBCTNIcKUSDii11ySs3526iDZ8A\niTo7Tu6KPAqv7D7gS2XpJFbZiItSs3m9+9Ue6GnvHw/GW2ZZaVtszggXIw==\n-----END PUBLIC KEY-----",
"PSA_IOT.impl-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=",
"PSA_IOT.inst-id": "Ac7rrnuJJ6MiflMDz14PH3s0u1Qq1yUKwD+83jbsLxUI"
}
}
ENDORSEMENTS:
-------------
{
"scheme": "PSA_IOT",
"type": "reference value",
"subType": "PSA_IOT.sw-component",
"attributes": {
"PSA_IOT.hw-model": "RoadRunner",
"PSA_IOT.hw-vendor": "ACME",
"PSA_IOT.impl-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=",
"PSA_IOT.measurement-desc": "sha-256",
"PSA_IOT.measurement-type": "PRoT",
"PSA_IOT.measurement-value": "MbgFqjT4jfR+fK1O4YyQtZUYD0nhXh7GfhM0EmR6tgc=",
"PSA_IOT.signer-id": "rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="
}
}TRUST ANCHORS は Attester から送信された evidence の署名を検証するためのデータを示しています。Attester から送信される evidence には impl-id と inst-id が含まれており、Verifier は受信した evidence をどの TRUST ANCHOR で検証するかを識別するためにそれらを用います。Verifier は識別された署名鍵(公開鍵)を用いて、CBOR(COSE) 形式の evidence を検証します。
iak-pub: evidence の署名を検証するための公開鍵(本プロジェクトでは ECDSA w/ SHA256 アルゴリズムが署名に用いられます。これは生成する evidence の形式が CBOR(COSE) であり、その仕様 RFC 8152 に準拠したものです。)impl-id: Attester の IDinst-id: 公開鍵の ID
ENDORSEMENTS は Attester から送信された evidence の内容を検証するためのデータ(オラクル)を示しています。Attester から送信される evidence には impl-id と measurment-value が含まれており、Verifier は受信した evidence をどの ENDORSEMENT と比較するかを識別するために impl-id を用います。Verifier は識別された ENDORSEMENT に記録されている measurement-value と受信した evidence に含まれる measurement-value を比較して、コードハッシュ値の正しさを検証します。その他の項目やより詳細な情報は仕様 Arm's Platform Security Architecture (PSA) Attestation Token を確認してください。
impl-id: Attester の IDmeasurement-value: コードハッシュ値(本プロジェクトでは PTA を呼び出す TA コードの SHA256)
次に、Relying Party を実行するためのコンテナを起動し、アプリケーションを実行します。Relying Party は、Attester からのリクエストを受け、Attester と Verifier の間の通信を仲介します。また、Verifier からアテステーション結果を受信すると、それをログに出力します。
./relying_party/container/start.shVerifier が https://verification-service:8080 以外で動作している場合は、起動前に VERIFICATION_SERVICE_URL を設定してください(デフォルト: https://verification-service:8080)。
VERIFICATION_SERVICE_URL=https://verification-service:8443 ./relying_party/container/start.sh以下のコマンドで Relying Party のログは確認できます。
docker logs relying-party-service正常に起動すると、以下のような出力が得られます。
go build -o rp main.go
./rp
2024/02/22 05:17:54 Relying party is starting...次に、アテステーションリクエストを送信する Attester を起動します。コンテナ上の QEMU の上で Attester を動作させる環境を準備しています。以下の 5 つの手順に従い、コンテナの起動し、 Verifier との通信プログラムを実行してください。
以下のコマンドを実行すると、Docker コンテナ上に入ります。注意として、初期実行時にはイメージのビルドに時間がかかるため、コンテナが起動するのに数十分かかることがあります。
./attester/container/start.sh手順 4.1. でコンテナを起動したターミナルとは別のターミナルを開き、以下を実行してください。QEMU 上で実行する Attester の normal world に接続する用のターミナルが準備されます。
./attester/container/launch_soc_term.sh normal手順 4.1. と 4.2. で使用したターミナルとは別のターミナルを開き、以下を実行してください。QEMU 上で実行する Attester の secure world に接続する用のターミナルが準備されます。
./attester/container/launch_soc_term.sh secure手順 4.1. で起動したターミナルで以下コマンドをを実行してください。ユーザが追加した CA/TA/PTA を再ビルドし、QEMU を起動します。コンテナイメージが /optee/optee_os/core/pta/sub.mk に subdirs-y += remote_attestation を自動で追加するため、手動編集は不要です。
make -C ${OPTEE_DIR}/build run CFG_REMOTE_ATTESTATION_PTA=y -jQEMU が立ち上がったら、c を入力します。
(qemu) c次に、normal world のターミナル(2. で起動したターミナル)上で、test ユーザでログインします。
buildroot login: testプログラムは normal world のターミナル上で起動します。 開発した evidence 生成プログラムを実行する場合は、以下のコマンドで実行できます。
optee_remote_attestation正しく実行できた場合、以下のような出力が noromal world のターミナルで得られます。
Opened new Veraison client session at http://relying-party-service:8087/challenge-response/v1/session/ed70cc0d-d141-11ee-9588-623338313838
Number of media types accepted: 7
application/vnd.parallaxsecond.key-attestation.cca
application/vnd.parallaxsecond.key-attestation.tpm
application/pem-certificate-chain
application/vnd.enacttrust.tpm-evidence
application/eat-collection; profile=http://arm.com/CCA-SSD/1.0.0
application/psa-attestation-token
application/eat-cwt; profile=http://arm.com/psa/2.0.0
Nonce size: 32 bytes
Nonce: [0x60, 0x48, 0xbd, 0x24, 0x55, 0xdb, 0x8a, 0x4, 0x6e, 0xcc, 0x7, 0x20, 0x40, 0x26, 0x87, 0xd0, 0x60, 0x72, 0xd, 0x95, 0x45, 0x57, 0x92, 0xa5, 0x36, 0xf4, 0x84, 0x52, 0xd5, 0xee, 0x5d, 0xbe]
Completed opening the session.
Invoke TA.
Invoked TA successfully.
Received evidence of CBOR (COSE) format from PTA.
CBOR(COSE) size: 306
CBOR(COSE): d28443a10126a058e7a71901097818687474703a2f2f61726d2e636f6d2f7073612f322e302e3019095a0119095b19300019095c582061636d652d696d706c656d656e746174696f6e2d69642d30303030303030303119095f81a3016450526f5402582031b805aa34f88df47e7cad4ee18c90b595180f49e15e1ec67e133412647ab607055820acbb11c7e4da217205523ce4ce1a245ae1a239ae3c6bfd9e7871f7e5d8bae86b0a58206048bd2455db8a046ecc0720402687d060720d95455792a536f48452d5ee5dbe190100582101ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f15085840fd39ee2aac4f64be2a58c1eca501ec1a3a7528f73bcbe8a90e7e1efda7e2cfce793fd28137c8a966793b605981fa677824867b22e21efcd6908338c4e3083b08
Supplying the generated evidence to the server.
Received the attestation result from the server.
Raw attestation result (JWT): eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJlYXIudmVyaWZpZXItaWQiOnsiYnVpbGQiOiJOL0EiLCJkZXZlbG9wZXIiOiJWZXJhaXNvbiBQcm9qZWN0In0sImVhdF9ub25jZSI6IllFaTlKRlhiaWdSdXpBY2dRQ2FIMEdCeURaVkZWNUtsTnZTRVV0WHVYYjQ9IiwiZWF0X3Byb2ZpbGUiOiJ0YWc6Z2l0aHViLmNvbSwyMDIzOnZlcmFpc29uL2VhciIsImlhdCI6MTcwODU3OTE1OSwic3VibW9kcyI6eyJQU0FfSU9UIjp7ImVhci5hcHByYWlzYWwtcG9saWN5LWlkIjoicG9saWN5OlBTQV9JT1QiLCJlYXIuc3RhdHVzIjoiYWZmaXJtaW5nIiwiZWFyLnRydXN0d29ydGhpbmVzcy12ZWN0b3IiOnsiY29uZmlndXJhdGlvbiI6MCwiZXhlY3V0YWJsZXMiOjIsImZpbGUtc3lzdGVtIjowLCJoYXJkd2FyZSI6MiwiaW5zdGFuY2UtaWRlbnRpdHkiOjIsInJ1bnRpbWUtb3BhcXVlIjoyLCJzb3VyY2VkLWRhdGEiOjAsInN0b3JhZ2Utb3BhcXVlIjoyfSwiZWFyLnZlcmFpc29uLmFubm90YXRlZC1ldmlkZW5jZSI6eyJlYXQtcHJvZmlsZSI6Imh0dHA6Ly9hcm0uY29tL3BzYS8yLjAuMCIsInBzYS1jbGllbnQtaWQiOjEsInBzYS1pbXBsZW1lbnRhdGlvbi1pZCI6IllXTnRaUzFwYlhCc1pXMWxiblJoZEdsdmJpMXBaQzB3TURBd01EQXdNREU9IiwicHNhLWluc3RhbmNlLWlkIjoiQWM3cnJudUpKNk1pZmxNRHoxNFBIM3MwdTFRcTF5VUt3RCs4M2pic0x4VUkiLCJwc2Etbm9uY2UiOiJZRWk5SkZYYmlnUnV6QWNnUUNhSDBHQnlEWlZGVjVLbE52U0VVdFh1WGI0PSIsInBzYS1zZWN1cml0eS1saWZlY3ljbGUiOjEyMjg4LCJwc2Etc29mdHdhcmUtY29tcG9uZW50cyI6W3sibWVhc3VyZW1lbnQtdHlwZSI6IlBSb1QiLCJtZWFzdXJlbWVudC12YWx1ZSI6Ik1iZ0ZxalQ0amZSK2ZLMU80WXlRdFpVWUQwbmhYaDdHZmhNMEVtUjZ0Z2M9Iiwic2lnbmVyLWlkIjoickxzUngrVGFJWElGVWp6a3pob2tXdUdpT2E0OGEvMmVlSEgzNWRpNjZHcz0ifV19fX19.PCUUBd6tyV2WdXuM07de3-ZFpKdoL-uEP7yeP1zNEJOpEJ9sVUDJkINI3nalh7nno2etEitbQABZxBCsy_6tKg
Disposing client session.
Completed sending the evidence and receiving the attestation result.もう一つターミナルを開き、以下のコマンドでrelying party のターミナルのログを確認できます。
docker logs relying-party-serviceアテステーション結果は ear.status の欄に記載されており、affirming であれば正しいアテステーション結果が得られたことを意味しています。
ear.status が warning で executables not recognized のようなログが出る場合は、古いエンドースメントが残っています。env.bash を source したシェルでストアをクリアし、provisioning をやり直してください(実機は imx を指定します)。
veraison clear-stores
./provisoning/run.sh qemu2024/02/22 05:19:18 Received request: POST /challenge-response/v1/newSession?nonceSize=32
2024/02/22 05:19:18 Received response: 201 Created
2024/02/22 05:19:19 Received request: POST /challenge-response/v1/session/ed70cc0d-d141-11ee-9588-623338313838
2024/02/22 05:19:19 Received response: 200 OK
2024/02/22 05:19:19 Attestation result: >> "/tmp/1442613949.jwt" signature successfully verified using "pkey.json"
[claims-set]
{
"ear.verifier-id": {
"build": "N/A",
"developer": "Veraison Project"
},
"eat_nonce": "YEi9JFXbigRuzAcgQCaH0GByDZVFV5KlNvSEUtXuXb4=",
"eat_profile": "tag:github.com,2023:veraison/ear",
"iat": 1708579159,
"submods": {
"PSA_IOT": {
"ear.appraisal-policy-id": "policy:PSA_IOT",
"ear.status": "affirming",
"ear.trustworthiness-vector": {
"configuration": 0,
"executables": 2,
"file-system": 0,
"hardware": 2,
"instance-identity": 2,
"runtime-opaque": 2,
"sourced-data": 0,
"storage-opaque": 2
},
"ear.veraison.annotated-evidence": {
"eat-profile": "http://arm.com/psa/2.0.0",
"psa-client-id": 1,
"psa-implementation-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=",
"psa-instance-id": "Ac7rrnuJJ6MiflMDz14PH3s0u1Qq1yUKwD+83jbsLxUI",
"psa-nonce": "YEi9JFXbigRuzAcgQCaH0GByDZVFV5KlNvSEUtXuXb4=",
"psa-security-lifecycle": 12288,
"psa-software-components": [
{
"measurement-type": "PRoT",
"measurement-value": "MbgFqjT4jfR+fK1O4YyQtZUYD0nhXh7GfhM0EmR6tgc=",
"signer-id": "rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="
}
]
}
}
}
}
[trustworthiness vectors]
submod(PSA_IOT):
Instance Identity [affirming]: The Attesting Environment is recognized, and the associated instance of the Attester is not known to be compromised.
Configuration [none]: The Evidence received is insufficient to make a conclusion.
Executables [affirming]: Only a recognized genuine set of approved executables, scripts, files, and/or objects have been loaded during and after the boot process.
File System [none]: The Evidence received is insufficient to make a conclusion.
Hardware [affirming]: An Attester has passed its hardware and/or firmware verifications needed to demonstrate that these are genuine/supported.
Runtime Opaque [affirming]: the Attester's executing Target Environment and Attesting Environments are encrypted and within Trusted Execution Environment(s) opaque to the operating system, virtual machine manager, and peer applications.
Storage Opaque [affirming]: the Attester encrypts all secrets in persistent storage via using keys which are never visible outside an HSM or the Trusted Execution Environment hardware.
Sourced Data [none]: The Evidence received is insufficient to make a conclusion.ここまでで、リモートアテステーションが成功する一連の流れを確認しました。次に、異なる TA からアテステーションリクエストを送った際に失敗するシナリオと、新たな endorsment を登録することでアテステーションが成功されるシナリオを確認します。
はじめに、録されてない TA から PTA にリクエストを送り、リモートアテステーションが失敗する流れを確認します。例えば、以下のように attester/remote_attestation/ta/include/remote_attestation_ta.h の IMPLEMENTATION_ID を書き換えると、TA のコードハッシュと implementation ID が変わり、PTA が生成する CBOR(COSE) evidence の内容が変わります。これにより、provisioning されているデータと異なるので、アテステーションが失敗するはずです。
diff --git a/attester/remote_attestation/ta/include/remote_attestation_ta.h b/attester/remote_attestation/ta/include/remote_attestation_ta.h
index 4380753..d9cad98 100644
--- a/attester/remote_attestation/ta/include/remote_attestation_ta.h
+++ b/attester/remote_attestation/ta/include/remote_attestation_ta.h
@@ -16,7 +16,7 @@
#define TA_REMOTE_ATTESTATOIN_CMD_GEN_CBOR_EVIDENCE 0
/* Implementation ID used in PSA evidence */
-#define IMPLEMENTATION_ID "acme-implementation-id-000000001"
+#define IMPLEMENTATION_ID "acme-implementation-id-000000002"
#define IMPLEMENTATION_ID_LEN 32
#if defined(HOST_BUILD)
実際に、コードを書き換えた後にアテステーションリクエストを送信してみます。手順 4.4. で QEMU を起動したターミナルで ctrl+c をして、一度 QEMU を終了します。その後、もう一度手順 4.4 に従い、TA の再ビルド・QEMU の再起動をします。
その後、手順 4.5. に従い、アテステーションリクエストを送り、手順 5. に従い結果を確認すると、以下のようなアテステーション結果が得られます。"ear.status": "contraindicated" になっており、アテステーションに失敗していることがわかります。
2024/02/22 05:36:19 Received request: POST /challenge-response/v1/newSession?nonceSize=32
2024/02/22 05:36:19 Received response: 201 Created
2024/02/22 05:36:20 Received request: POST /challenge-response/v1/session/4e2f256e-d144-11ee-9588-623338313838
2024/02/22 05:36:20 Received response: 200 OK
2024/02/22 05:36:20 Attestation result: >> "/tmp/3383640462.jwt" signature successfully verified using "pkey.json"
[claims-set]
{
"ear.verifier-id": {
"build": "commit-b50b67d",
"developer": "Veraison Project"
},
"eat_nonce": "J5um9vO4NYv8hYqPXUWsYuuWgW0TLV0qoZGQk3EnIUg=",
"eat_profile": "tag:github.com,2023:veraison/ear",
"iat": 1708580180,
"submods": {
"PSA_IOT": {
"ear.appraisal-policy-id": "policy:PSA_IOT",
"ear.status": "contraindicated",
"ear.trustworthiness-vector": {
"configuration": 99,
"executables": 99,
"file-system": 99,
"hardware": 99,
"instance-identity": 99,
"runtime-opaque": 99,
"sourced-data": 99,
"storage-opaque": 99
},
"ear.veraison.policy-claims": {
"problem": "no trust anchor for evidence"
}
}
}
}
[trustworthiness vectors]
submod(PSA_IOT):
Instance Identity [contraindicated]: Cryptographic validation of the Evidence has failed.
Configuration [contraindicated]: Cryptographic validation of the Evidence has failed.
Executables [contraindicated]: Cryptographic validation of the Evidence has failed.
File System [contraindicated]: Cryptographic validation of the Evidence has failed.
Hardware [contraindicated]: Cryptographic validation of the Evidence has failed.
Runtime Opaque [contraindicated]: Cryptographic validation of the Evidence has failed.
Storage Opaque [contraindicated]: Cryptographic validation of the Evidence has failed.
Sourced Data [contraindicated]: Cryptographic validation of the Evidence has failed.はじめに、新たな TA のコードハッシュ値を確認します。現在、PTA に evidence 生成リクエストを送ると、secure terminal にコードハッシュ値がデバッグ用に出力される実装になっています。具体的には以下のような一行があり、gw9v98IV8ozl5nHpsMwl9W5nGGC0bzAYMPShwvff0vY= がコードハッシュ値を base64 エンコードした値です。
D/TC:? 0 cmd_get_cbor_evidence:82 b64_measurement_value: gw9v98IV8ozl5nHpsMwl9W5nGGC0bzAYMPShwvff0vY=この値を provisioning で登録します。そのためには、provisoning/data/comid-psa-refval-qemu.json の digests の欄を以下のように書き換えてください(実機の場合は provisoning/data/comid-psa-refval-imx.json を使います)。
また、implementation ID も acme-implementation-id-000000002 に変更しているため、provisoning/data/comid-psa-refval-qemu.json と provisoning/data/comid-psa-ta.json の psa.impl-id の欄を以下のように書き換えてください。注意しとして、psa.impl-id の欄は implementation ID を base64 エンコードした値を登録する必要があります。例えば、echo -n "acme-implementation-id-000000002" | base64 のようなコマンドで計算できます。
diff --git a/provisoning/data/comid-psa-refval-qemu.json b/provisoning/data/comid-psa-refval-qemu.json
index fd7965a..db675c1 100644
--- a/provisoning/data/comid-psa-refval-qemu.json
+++ b/provisoning/data/comid-psa-refval-qemu.json
@@ -22,7 +22,7 @@
"class": {
"id": {
"type": "psa.impl-id",
- "value": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE="
+ "value": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDI="
},
"vendor": "ACME",
"model": "RoadRunner"
@@ -39,7 +39,7 @@
},
"value": {
"digests": [
- "sha-256;MbgFqjT4jfR+fK1O4YyQtZUYD0nhXh7GfhM0EmR6tgc="
+ "sha-256;gw9v98IV8ozl5nHpsMwl9W5nGGC0bzAYMPShwvff0vY="
]
}
}
diff --git a/provisoning/data/comid-psa-ta.json b/provisoning/data/comid-psa-ta.json
index 7396dbd..9a813c3 100644
--- a/provisoning/data/comid-psa-ta.json
+++ b/provisoning/data/comid-psa-ta.json
@@ -22,7 +22,7 @@
"class": {
"id": {
"type": "psa.impl-id",
- "value": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE="
+ "value": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDI="
},
"vendor": "ACME",
"model": "RoadRunner"その後、手順 2. に従い、provisioning を再実行します。その結果、以下のように二つの TRUST ANCHORS と ENDORSEMENTS が登録され、PSA_IOT.impl-id と PSA_IOT.measurement-value の部分のみが異なることを確認できます。
TRUST ANCHORS:
--------------
{
"scheme": "PSA_IOT",
"type": "trust anchor",
"subType": "",
"attributes": {
"PSA_IOT.hw-model": "RoadRunner",
"PSA_IOT.hw-vendor": "ACME",
"PSA_IOT.iak-pub": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMKBCTNIcKUSDii11ySs3526iDZ8A\niTo7Tu6KPAqv7D7gS2XpJFbZiItSs3m9+9Ue6GnvHw/GW2ZZaVtszggXIw==\n-----END PUBLIC KEY-----",
"PSA_IOT.impl-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=",
"PSA_IOT.inst-id": "Ac7rrnuJJ6MiflMDz14PH3s0u1Qq1yUKwD+83jbsLxUI"
}
}
{
"scheme": "PSA_IOT",
"type": "trust anchor",
"subType": "",
"attributes": {
"PSA_IOT.hw-model": "RoadRunner",
"PSA_IOT.hw-vendor": "ACME",
"PSA_IOT.iak-pub": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMKBCTNIcKUSDii11ySs3526iDZ8A\niTo7Tu6KPAqv7D7gS2XpJFbZiItSs3m9+9Ue6GnvHw/GW2ZZaVtszggXIw==\n-----END PUBLIC KEY-----",
"PSA_IOT.impl-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDI=",
"PSA_IOT.inst-id": "Ac7rrnuJJ6MiflMDz14PH3s0u1Qq1yUKwD+83jbsLxUI"
}
}
ENDORSEMENTS:
-------------
{
"scheme": "PSA_IOT",
"type": "reference value",
"subType": "PSA_IOT.sw-component",
"attributes": {
"PSA_IOT.hw-model": "RoadRunner",
"PSA_IOT.hw-vendor": "ACME",
"PSA_IOT.impl-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=",
"PSA_IOT.measurement-desc": "sha-256",
"PSA_IOT.measurement-type": "PRoT",
"PSA_IOT.measurement-value": "MbgFqjT4jfR+fK1O4YyQtZUYD0nhXh7GfhM0EmR6tgc=",
"PSA_IOT.signer-id": "rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="
}
}
{
"scheme": "PSA_IOT",
"type": "reference value",
"subType": "PSA_IOT.sw-component",
"attributes": {
"PSA_IOT.hw-model": "RoadRunner",
"PSA_IOT.hw-vendor": "ACME",
"PSA_IOT.impl-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDI=",
"PSA_IOT.measurement-desc": "sha-256",
"PSA_IOT.measurement-type": "PRoT",
"PSA_IOT.measurement-value": "gw9v98IV8ozl5nHpsMwl9W5nGGC0bzAYMPShwvff0vY=",
"PSA_IOT.signer-id": "rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="
}
}その後、手順 4.5. に従いアテステーションリクエストを送り、手順 5. に従い結果を確認すると、以下のようなアテステーション結果が得られます。"ear.status": "affirming" になっており、アテステーションに成功していることがわかります。
[claims-set]
{
"ear.verifier-id": {
"build": "N/A",
"developer": "Veraison Project"
},
"eat_nonce": "yBULiGEcBq8wtk5xwRikzPZt1GAV5n8L0nXgPY03jHo=",
"eat_profile": "tag:github.com,2023:veraison/ear",
"iat": 1708581024,
"submods": {
"PSA_IOT": {
"ear.appraisal-policy-id": "policy:PSA_IOT",
"ear.status": "affirming",
"ear.trustworthiness-vector": {
"configuration": 0,
"executables": 2,
"file-system": 0,
"hardware": 2,
"instance-identity": 2,
"runtime-opaque": 2,
"sourced-data": 0,
"storage-opaque": 2
},
"ear.veraison.annotated-evidence": {
"eat-profile": "http://arm.com/psa/2.0.0",
"psa-client-id": 1,
"psa-implementation-id": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDI=",
"psa-instance-id": "Ac7rrnuJJ6MiflMDz14PH3s0u1Qq1yUKwD+83jbsLxUI",
"psa-nonce": "yBULiGEcBq8wtk5xwRikzPZt1GAV5n8L0nXgPY03jHo=",
"psa-security-lifecycle": 12288,
"psa-software-components": [
{
"measurement-type": "PRoT",
"measurement-value": "gw9v98IV8ozl5nHpsMwl9W5nGGC0bzAYMPShwvff0vY=",
"signer-id": "rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="
}
]
}
}
}
}以下のコマンドでこのテストのために立ち上げたコンテナなどを停止することができます。
make -C services really-clean
docker stop relying-party-service
docker network rm veraison-net本セクションでは i.MX8MP EVK 実機上で PSA Remote Attestation を実行し、 Veraison で検証する手順を説明します。埋め込みテスト鍵、CAAM ブラックキー新規生成、 既存鍵の変換の 3 つのシナリオを扱います。
必要環境:
- Docker
- 約100GB の空き容量(初回)
- 4-8時間のビルド時間(初回)
フルイメージのビルド(リポジトリ直下から):
cd attester/container-imx
./yocto.shtmpfs を使って高速化する場合:
YOCTO_DIR=/dev/shm/yocto ./yocto.sh注意: tmpfs では一部パッケージ(例: gdk-pixbuf-native)のビルドが失敗する場合があります。その場合は通常のファイルシステムを使用してください。
部分的な再ビルド:
./yocto.sh optee-os
./yocto.sh veraison-attestation注意: i.MX8MP は SD 先頭の imx-boot に埋め込まれた tee.bin を使用します。./yocto.sh optee-os は imx-boot の再ビルドまで実行しますが、SD 書き込み用の WIC を更新するには ./yocto.sh(full)で再パッケージしてください。
出力イメージ:
${YOCTO_DIR}/build/tmp/deploy/images/imx8mpevk/core-image-minimal-imx8mpevk.rootfs.wic.zst
SD カードへの書き込み:
cd ${YOCTO_DIR}/build/tmp/deploy/images/imx8mpevk/
zstd -d core-image-minimal-imx8mpevk.rootfs.wic.zst
sudo dd if=core-image-minimal-imx8mpevk.rootfs.wic of=/dev/sdX bs=4M status=progress && sync/dev/sdX は実際の SD カードデバイスに置き換えてください。
| 項目 | 詳細 |
|---|---|
| ボード | i.MX8MP EVK |
| ビルド | core-image-minimal (Yocto + OP-TEE + veraison-attestation PTA) |
| Veraison | Docker デプロイメント (services/deployments/docker/) |
| ネットワーク | デバイスと Veraison ホストが IP 到達可能 |
| SD カード | imx-boot と rootfs の両方を含む WIC イメージ |
重要: i.MX8MP は SD カード先頭の imx-boot 内の
tee.binを使用します。 rootfs 上の/usr/lib/firmware/tee.binを更新しても Secure World には 反映されません。PTA のコード変更を反映するには imx-boot を含む WIC イメージ全体 を再フラッシュする必要があります。
デバイス側で Veraison ホストを /etc/hosts に追加:
echo "<Veraison_Host_IP> relying-party-service" >> /etc/hostsVeraison ホスト側でサービスを起動:
services/deployments/docker/veraison start
source services/deployments/docker/env.bash全シナリオ共通で instance-id = 0x01 || SHA-256(0x04 || PubX || PubY) です。
CAAM 鍵を使う場合(シナリオ B, C)は、ホスト側で PubX/PubY から instance ID と
PEM 公開鍵を計算します:
python3 -c "
import hashlib, base64
pub_x = bytes.fromhex('<PubX hex>')
pub_y = bytes.fromhex('<PubY hex>')
digest = hashlib.sha256(b'\x04' + pub_x + pub_y).digest()
instance_id = b'\x01' + digest
print('instance_id (base64):', base64.b64encode(instance_id).decode())
"python3 -c "
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
pub_x = bytes.fromhex('<PubX hex>')
pub_y = bytes.fromhex('<PubY hex>')
pub_numbers = ec.EllipticCurvePublicNumbers(
x=int.from_bytes(pub_x, 'big'),
y=int.from_bytes(pub_y, 'big'),
curve=ec.SECP256R1()
)
pub_key = pub_numbers.public_key()
pem = pub_key.public_bytes(
serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo
).decode()
print(pem.strip())
"計算した値で provisoning/data/comid-psa-ta.json の instance と
verification-keys を更新してください。
PTA に埋め込まれたテスト用 ECDSA P-256 鍵で evidence に署名します。 デバイス側での鍵管理は不要です。
| 項目 | 値 |
|---|---|
| PubX | 30a0424cd21c2944838a2d75c92b37e76ea20d9f00893a3b4eee8a3c0aafec3e |
| PubY | e04b65e92456d9888b52b379bdfbd51ee869ef1f0fc65b6659695b6cce081723 |
| Instance ID | AZDHHoAwT5jWVWpALAWTszqArL0I5K/5xAKfbhfhA5lR |
Provisioning:
services/deployments/docker/veraison clear-stores
./provisoning/run.sh imxデフォルトの comid-psa-ta.json にはテスト鍵の trust anchor が設定済みです。
Attestation 実行 (デバイス側):
optee_remote_attestation期待される結果: "ear.status": "affirming"
CAAM モジュールで新しい ECDSA P-256 鍵ペアを生成します。 秘密鍵は JDKEK で暗号化されており、プレーンテキストではメモリ上に露出しません。
注意: ブラックキーは JDKEK (揮発性) で暗号化されています。 電源サイクルで JDKEK が再生成されるため、同一ブートセッション内でのみ使用可能です。
手順 1 — 鍵生成 (デバイス側):
optee_remote_attestation --generate-blackkey出力例:
Generating new black key...
BlackKey(hex): fbbfafca020000002000000...
PubX(hex): 3d87f38e7b34e5c0bc988becb225783daa4d14dc0031f49588fe61708c4f1f6f
PubY(hex): 15dc6990d4209e3cb1f732310a4784a535a93962b7d87274286026ec80153ce4
FullKey(hex): 3d87f38e7b34e5c0...fbbfafca020000002000000...
Black key generation completed.
手順 2 — Provisioning (ホスト側): PubX/PubY から instance ID と PEM 公開鍵を
計算し(上記ヘルパー参照)、comid-psa-ta.json を更新後:
services/deployments/docker/veraison clear-stores
./provisoning/run.sh imx手順 3 — Attestation 実行 (デバイス側): FullKey をそのまま渡す:
optee_remote_attestation --key-hex <FullKey hex>または各コンポーネントを個別に渡す:
optee_remote_attestation --key-hex <BlackKey hex> --pubx-hex <PubX hex> --puby-hex <PubY hex>期待される結果: "ear.status": "affirming"
既存のプレーンテキスト ECDSA P-256 秘密鍵(32 バイトの d 値)を
CAAM ブラックキーに変換します。OpenSSL 等で生成済みの鍵ペアがある場合に使用します。
手順 1 — 鍵変換 (デバイス側):
optee_remote_attestation --convert-key <32バイト秘密鍵 hex>出力例:
Converting plain key to black key...
BlackKey(hex): fbbfafca020000002000000...
Key conversion completed.
公開鍵 (PubX/PubY) は出力されません。元の鍵ペアから既知のためです。
手順 2 — Provisioning (ホスト側): 既知の PubX/PubY から instance ID と
PEM 公開鍵を計算し(上記ヘルパー参照)、comid-psa-ta.json を更新後:
services/deployments/docker/veraison clear-stores
./provisoning/run.sh imx手順 3 — Attestation 実行 (デバイス側):
optee_remote_attestation --key-hex <BlackKey hex> --pubx-hex <PubX hex> --puby-hex <PubY hex>期待される結果: "ear.status": "affirming"
研究は、JST、CREST、JPMJCR21M3 (Zero Trust IoT プロジェクト) の支援を受けたものです。