Interaction between Measured Boot and an fTPM (PoC) =================================================== Measured Boot is the process of cryptographically measuring the code and critical data used at boot time, for example using a TPM, so that the security state can be attested later. The current implementation of the driver included in Trusted Firmware-A (TF-A) stores the measurements into a `TGC event log`_ in secure memory. No other means of recording measurements (such as a discrete TPM) is supported right now. The driver also provides mechanisms to pass the Event Log to normal world if needed. This manual provides instructions to build a proof of concept (PoC) with the sole intention of showing how Measured Boot can be used in conjunction with a firmware TPM (fTPM) service implemented on top of OP-TEE. .. note:: The instructions given in this document are meant to be used to build a PoC to show how Measured Boot on TF-A can interact with a third party (f)TPM service and they try to be as general as possible. Different platforms might have different needs and configurations (e.g. different SHA algorithms) and they might also use different types of TPM services (or even a different type of service to provide the attestation) and therefore the instuctions given here might not apply in such scenarios. Components ~~~~~~~~~~ The PoC is built on top of the `OP-TEE Toolkit`_, which has support to build TF-A with support for Measured Boot enabled (and run it on a Foundation Model) since commit cf56848. The aforementioned toolkit builds a set of images that contain all the components needed to test that the Event Log was properly created. One of these images will contain a third party fTPM service which in turn will be used to process the Event Log. The reason to choose OP-TEE Toolkit to build our PoC around it is mostly for convenience. As the fTPM service used is an OP-TEE TA, it was easy to add build support for it to the toolkit and then build the PoC around it. The most relevant components installed in the image that are closely related to Measured Boot/fTPM functionality are: - **OP-TEE**: As stated earlier, the fTPM service used in this PoC is built as an OP-TEE TA and therefore we need to include the OP-TEE OS image. Support to interfacing with Measured Boot was added to version 3.9.0 of OP-TEE by implementing the ``PTA_SYSTEM_GET_TPM_EVENT_LOG`` syscall, which allows the former to pass a copy of the Event Log to any TA requesting it. OP-TEE knows the location of the Event Log by reading the DTB bindings received from TF-A. Visit :ref:`DTB binding for Event Log properties` for more details on this. - **fTPM Service**: We use a third party fTPM service in order to validate the Measured Boot functionality. The chosen fTPM service is a sample implementation for Aarch32 architecture included on the `ms-tpm-20-ref`_ reference implementation from Microsoft. The service was updated in order to extend the Measured Boot Event Log at boot up and it uses the aforementioned ``PTA_SYSTEM_GET_TPM_EVENT_LOG`` call to retrieve a copy of the former. .. note:: Arm does not provide an fTPM implementation. The fTPM service used here is a third party one which has been updated to support Measured Boot service as provided by TF-A. As such, it is beyond the scope of this manual to test and verify the correctness of the output generated by the fTPM service. - **TPM Kernel module**: In order to interact with the fTPM service, we need a kernel module to forward the request from user space to the secure world. - `tpm2-tools`_: This is a set of tools that allow to interact with the fTPM service. We use this in order to read the PCRs with the measurements. Building the PoC for the Arm FVP platform ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As mentioned before, this PoC is based on the OP-TEE Toolkit with some extensions to enable Measured Boot and an fTPM service. Therefore, we can rely on the instructions to build the original OP-TEE Toolkit. As a general rule, the following steps should suffice: (1) Start by following the `Get and build the solution`_ instructions to build the OP-TEE toolkit. On step 3, you need to get the manifest for FVP platform from the main branch: .. code:: shell $ repo init -u https://github.com/OP-TEE/manifest.git -m fvp.xml Then proceed synching the repos as stated in step 3. Continue following the instructions and stop before step 5. (2) Next you should obtain the `Armv8-A Foundation Platform (For Linux Hosts Only)`_. The binary should be untar'ed to the root of the repo tree, i.e., like this: ``/Foundation_Platformpkg``. In the end, after cloning all source code, getting the toolchains and "installing" Foundation_Platformpkg, you should have a folder structure that looks like this: .. code:: shell $ ls -la total 80 drwxrwxr-x 20 tf-a_user tf-a_user 4096 Jul 1 12:16 . drwxr-xr-x 23 tf-a_user tf-a_user 4096 Jul 1 10:40 .. drwxrwxr-x 12 tf-a_user tf-a_user 4096 Jul 1 10:45 build drwxrwxr-x 16 tf-a_user tf-a_user 4096 Jul 1 12:16 buildroot drwxrwxr-x 51 tf-a_user tf-a_user 4096 Jul 1 10:45 edk2 drwxrwxr-x 6 tf-a_user tf-a_user 4096 Jul 1 12:14 edk2-platforms drwxr-xr-x 7 tf-a_user tf-a_user 4096 Jul 1 10:52 Foundation_Platformpkg drwxrwxr-x 17 tf-a_user tf-a_user 4096 Jul 2 10:40 grub drwxrwxr-x 25 tf-a_user tf-a_user 4096 Jul 2 10:39 linux drwxrwxr-x 15 tf-a_user tf-a_user 4096 Jul 1 10:45 mbedtls drwxrwxr-x 6 tf-a_user tf-a_user 4096 Jul 1 10:45 ms-tpm-20-ref drwxrwxr-x 8 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_client drwxrwxr-x 10 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_examples drwxrwxr-x 12 tf-a_user tf-a_user 4096 Jul 1 12:13 optee_os drwxrwxr-x 8 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_test drwxrwxr-x 7 tf-a_user tf-a_user 4096 Jul 1 10:45 .repo drwxrwxr-x 4 tf-a_user tf-a_user 4096 Jul 1 12:12 toolchains drwxrwxr-x 21 tf-a_user tf-a_user 4096 Jul 1 12:15 trusted-firmware-a (3) Now enter into ``ms-tpm-20-ref`` and get its dependencies: .. code:: shell $ cd ms-tpm-20-ref $ git submodule init $ git submodule update Submodule path 'external/wolfssl': checked out '9c87f979a7f1d3a6d786b260653d566c1d31a1c4' (4) Now, you should be able to continue with step 5 in "`Get and build the solution`_" instructions. In order to enable support for Measured Boot, you need to set the ``MEASURED_BOOT`` build option: .. code:: shell $ MEASURED_BOOT=y make -j `nproc` .. note:: The build process will likely take a long time. It is strongly recommended to pass the ``-j`` option to make to run the process faster. After this step, you should be ready to run the image. Running and using the PoC on the Armv8-A Foundation AEM FVP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ With everything built, you can now run the image: .. code:: shell $ make run-only .. note:: Using ``make run`` will build and run the image and it can be used instead of simply ``make``. However, once the image is built, it is recommended to use ``make run-only`` to avoid re-running all the building rules, which would take time. When FVP is launched, two terminal windows will appear. ``FVP terminal_0`` is the userspace terminal whereas ``FVP terminal_1`` is the counterpart for the secure world (where TAs will print their logs, for instance). Log into the image shell with user ``root``, no password will be required. Then we can issue the ``ftpm`` command, which is an alias that (1) loads the ftpm kernel module and (2) calls ``tpm2_pcrread``, which will access the fTPM service to read the PCRs. When loading the ftpm kernel module, the fTPM TA is loaded into the secure world. This TA then requests a copy of the Event Log generated during the booting process so it can retrieve all the entries on the log and record them first thing. .. note:: For this PoC, nothing loaded after BL33 and NT_FW_CONFIG is recorded in the Event Log. The secure world terminal should show the debug logs for the fTPM service, including all the measurements available in the Event Log as they are being processed: .. code:: shell M/TA: Preparing to extend the following TPM Event Log: M/TA: TCG_EfiSpecIDEvent: M/TA: PCRIndex : 0 M/TA: EventType : 3 M/TA: Digest : 00 M/TA: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 M/TA: : 00 00 00 M/TA: EventSize : 33 M/TA: Signature : Spec ID Event03 M/TA: PlatformClass : 0 M/TA: SpecVersion : 2.0.2 M/TA: UintnSize : 1 M/TA: NumberOfAlgorithms : 1 M/TA: DigestSizes : M/TA: #0 AlgorithmId : SHA256 M/TA: DigestSize : 32 M/TA: VendorInfoSize : 0 M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 3 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 M/TA: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 M/TA: EventSize : 17 M/TA: Signature : StartupLocality M/TA: StartupLocality : 0 M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 58 26 32 6e 64 45 64 da 45 de 35 db 96 fd ed 63 M/TA: : 2a 6a d4 0d aa 94 b0 b1 55 e4 72 e7 1f 0a e0 d5 M/TA: EventSize : 5 M/TA: Event : BL_2 M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : cf f9 7d a3 5c 73 ac cb 7b a0 25 80 6a 6e 50 a5 M/TA: : 6b 2e d2 8c c9 36 92 7d 46 c5 b9 c3 a4 6c 51 7c M/TA: EventSize : 6 M/TA: Event : BL_31 M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 23 b0 a3 5d 54 d9 43 1a 5c b9 89 63 1c da 06 c2 M/TA: : e5 de e7 7e 99 17 52 12 7d f7 45 ca 4f 4a 39 c0 M/TA: EventSize : 10 M/TA: Event : HW_CONFIG M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a M/TA: : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0 M/TA: EventSize : 14 M/TA: Event : SOC_FW_CONFIG M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 01 b0 80 47 a1 ce 86 cd df 89 d2 1f 2e fc 6c 22 M/TA: : f8 19 ec 6e 1e ec 73 ba 5a be d0 96 e3 5f 6d 75 M/TA: EventSize : 6 M/TA: Event : BL_32 M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 5d c6 ef 35 5a 90 81 b4 37 e6 3b 52 da 92 ab 8e M/TA: : d9 6e 93 98 2d 40 87 96 1b 5a a7 ee f1 f4 40 63 M/TA: EventSize : 18 M/TA: Event : BL32_EXTRA1_IMAGE M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 39 b7 13 b9 93 db 32 2f 1b 48 30 eb 2c f2 5c 25 M/TA: : 00 0f 38 dc 8e c8 02 cd 79 f2 48 d2 2c 25 ab e2 M/TA: EventSize : 6 M/TA: Event : BL_33 M/TA: PCR_Event2: M/TA: PCRIndex : 0 M/TA: EventType : 1 M/TA: Digests Count : 1 M/TA: #0 AlgorithmId : SHA256 M/TA: Digest : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6 M/TA: : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a M/TA: EventSize : 13 M/TA: Event : NT_FW_CONFIG These logs correspond to the measurements stored by TF-A during the measured boot process and therefore, they should match the logs dumped by the former during the boot up process. These can be seen on the terminal_0: .. code:: shell NOTICE: Booting Trusted Firmware NOTICE: BL1: v2.5(release):v2.5 NOTICE: BL1: Built : 10:41:20, Jul 2 2021 NOTICE: BL1: Booting BL2 NOTICE: BL2: v2.5(release):v2.5 NOTICE: BL2: Built : 10:41:20, Jul 2 2021 NOTICE: TCG_EfiSpecIDEvent: NOTICE: PCRIndex : 0 NOTICE: EventType : 3 NOTICE: Digest : 00 NOTICE: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 NOTICE: : 00 00 00 NOTICE: EventSize : 33 NOTICE: Signature : Spec ID Event03 NOTICE: PlatformClass : 0 NOTICE: SpecVersion : 2.0.2 NOTICE: UintnSize : 1 NOTICE: NumberOfAlgorithms : 1 NOTICE: DigestSizes : NOTICE: #0 AlgorithmId : SHA256 NOTICE: DigestSize : 32 NOTICE: VendorInfoSize : 0 NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 3 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 NOTICE: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 NOTICE: EventSize : 17 NOTICE: Signature : StartupLocality NOTICE: StartupLocality : 0 NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 58 26 32 6e 64 45 64 da 45 de 35 db 96 fd ed 63 NOTICE: : 2a 6a d4 0d aa 94 b0 b1 55 e4 72 e7 1f 0a e0 d5 NOTICE: EventSize : 5 NOTICE: Event : BL_2 NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : cf f9 7d a3 5c 73 ac cb 7b a0 25 80 6a 6e 50 a5 NOTICE: : 6b 2e d2 8c c9 36 92 7d 46 c5 b9 c3 a4 6c 51 7c NOTICE: EventSize : 6 NOTICE: Event : BL_31 NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 23 b0 a3 5d 54 d9 43 1a 5c b9 89 63 1c da 06 c2 NOTICE: : e5 de e7 7e 99 17 52 12 7d f7 45 ca 4f 4a 39 c0 NOTICE: EventSize : 10 NOTICE: Event : HW_CONFIG NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a NOTICE: : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0 NOTICE: EventSize : 14 NOTICE: Event : SOC_FW_CONFIG NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 01 b0 80 47 a1 ce 86 cd df 89 d2 1f 2e fc 6c 22 NOTICE: : f8 19 ec 6e 1e ec 73 ba 5a be d0 96 e3 5f 6d 75 NOTICE: EventSize : 6 NOTICE: Event : BL_32 NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 5d c6 ef 35 5a 90 81 b4 37 e6 3b 52 da 92 ab 8e NOTICE: : d9 6e 93 98 2d 40 87 96 1b 5a a7 ee f1 f4 40 63 NOTICE: EventSize : 18 NOTICE: Event : BL32_EXTRA1_IMAGE NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 39 b7 13 b9 93 db 32 2f 1b 48 30 eb 2c f2 5c 25 NOTICE: : 00 0f 38 dc 8e c8 02 cd 79 f2 48 d2 2c 25 ab e2 NOTICE: EventSize : 6 NOTICE: Event : BL_33 NOTICE: PCR_Event2: NOTICE: PCRIndex : 0 NOTICE: EventType : 1 NOTICE: Digests Count : 1 NOTICE: #0 AlgorithmId : SHA256 NOTICE: Digest : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6 NOTICE: : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a NOTICE: EventSize : 13 NOTICE: Event : NT_FW_CONFIG NOTICE: BL1: Booting BL31 NOTICE: BL31: v2.5(release):v2.5 NOTICE: BL31: Built : 10:41:20, Jul 2 2021 Following up with the fTPM startup process, we can see that all the measurements in the Event Log are extended and recorded in the appropriate PCR: .. code:: shell M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: TPM2_PCR_EXTEND_COMMAND returned value: M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 M/TA: 9 Event logs processed After the fTPM TA is loaded, the call to ``insmod`` issued by the ``ftpm`` alias to load the ftpm kernel module returns, and then the TPM PCRs are read by means of ``tpm_pcrread`` command. Note that we are only interested in the SHA256 logs here, as this is the algorithm we used on TF-A for the measurements (see the field ``AlgorithmId`` on the logs above): .. code:: shell sha256: 0 : 0xA6EB3A7417B8CFA9EBA2E7C22AD5A4C03CDB8F3FBDD7667F9C3EF2EA285A8C9F 1 : 0x0000000000000000000000000000000000000000000000000000000000000000 2 : 0x0000000000000000000000000000000000000000000000000000000000000000 3 : 0x0000000000000000000000000000000000000000000000000000000000000000 4 : 0x0000000000000000000000000000000000000000000000000000000000000000 5 : 0x0000000000000000000000000000000000000000000000000000000000000000 6 : 0x0000000000000000000000000000000000000000000000000000000000000000 7 : 0x0000000000000000000000000000000000000000000000000000000000000000 8 : 0x0000000000000000000000000000000000000000000000000000000000000000 9 : 0x0000000000000000000000000000000000000000000000000000000000000000 10: 0x0000000000000000000000000000000000000000000000000000000000000000 11: 0x0000000000000000000000000000000000000000000000000000000000000000 12: 0x0000000000000000000000000000000000000000000000000000000000000000 13: 0x0000000000000000000000000000000000000000000000000000000000000000 14: 0x0000000000000000000000000000000000000000000000000000000000000000 15: 0x0000000000000000000000000000000000000000000000000000000000000000 16: 0x0000000000000000000000000000000000000000000000000000000000000000 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 23: 0x0000000000000000000000000000000000000000000000000000000000000000 In this PoC we are only interested in PCR0, which must be non-null. This is because the boot process records all the images in this PCR (see field ``PCRIndex`` on the Event Log above). The rest of the records must be 0 at this point. .. note:: The fTPM service used has support only for 16 PCRs, therefore the content of PCRs above 15 can be ignored. .. note:: As stated earlier, Arm does not provide an fTPM implementation and therefore we do not validate here if the content of PCR0 is correct or not. For this PoC, we are only focused on the fact that the event log could be passed to a third party fTPM and its records were properly extended. Fine-tuning the fTPM TA ~~~~~~~~~~~~~~~~~~~~~~~ As stated earlier, the OP-TEE Toolkit includes support to build a third party fTPM service. The build options for this service are tailored for the PoC and defined in the build environment variable ``FTPM_FLAGS`` (see ``/build/common.mk``) but they can be modified if needed to better adapt it to a specific scenario. The most relevant options for Measured Boot support are: - **CFG_TA_DEBUG**: Enables debug logs in the Terminal_1 console. - **CFG_TEE_TA_LOG_LEVEL**: Defines the log level used for the debug messages. - **CFG_TA_MEASURED_BOOT**: Enables support for measured boot on the fTPM. - **CFG_TA_EVENT_LOG_SIZE**: Defines the size, in bytes, of the larger event log that the fTPM is able to store, as this buffer is allocated at build time. This must be at least the same as the size of the event log generated by TF-A. If this build option is not defined, the fTPM falls back to a default value of 1024 bytes, which is enough for this PoC, so this variable is not defined in FTPM_FLAGS. -------------- *Copyright (c) 2021, Arm Limited. All rights reserved.* .. _OP-TEE Toolkit: https://github.com/OP-TEE/build .. _ms-tpm-20-ref: https://github.com/microsoft/ms-tpm-20-ref .. _Get and build the solution: https://optee.readthedocs.io/en/latest/building/gits/build.html#get-and-build-the-solution .. _Armv8-A Foundation Platform (For Linux Hosts Only): https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models .. _tpm2-tools: https://github.com/tpm2-software/tpm2-tools .. _TGC event log: https://trustedcomputinggroup.org/resource/tcg-efi-platform-specification/