GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,165 @@
TF-A CMake buildsystem
======================
:Author: Balint Dobszay
:Organization: Arm Limited
:Contact: Balint Dobszay <balint.dobszay@arm.com>
:Status: Accepted
.. contents:: Table of Contents
Abstract
--------
This document presents a proposal for a new buildsystem for TF-A using CMake,
and as part of this a reusable CMake framework for embedded projects. For a
summary about the proposal, please see the `Phabricator wiki page
<https://developer.trustedfirmware.org/w/tf_a/cmake-buildsystem-proposal/>`_. As
mentioned there, the proposal consists of two phases. The subject of this
document is the first phase only.
Introduction
------------
The current Makefile based buildsystem of TF-A has become complicated and hard
to maintain, there is a need for a new, more flexible solution. The proposal is
to use CMake language for the new buildsystem. The main reasons of this decision
are the following:
* It is a well-established, mature tool, widely accepted by open-source
projects.
* TF-M is already using CMake, reducing fragmentation for tf.org projects can be
beneficial.
* CMake has various advantages over Make, e.g.:
* Host and target system agnostic project.
* CMake project is scalable, supports project modularization.
* Supports software integration.
* Out-of-the-box support for integration with several tools (e.g. project
generation for various IDEs, integration with cppcheck, etc).
Of course there are drawbacks too:
* Language is problematic (e.g. variable scope).
* Not embedded approach.
To overcome these and other problems, we need to create workarounds for some
tasks, wrap CMake functions, etc. Since this functionality can be useful in
other embedded projects too, it is beneficial to collect the new code into a
reusable framework and store this in a separate repository. The following
diagram provides an overview of the framework structure:
|Framework structure|
Main features
-------------
Structured configuration description
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the current Makefile system the build configuration description, validation,
processing, and the target creation, source file description are mixed and
spread across several files. One of the goals of the framework is to organize
this.
The framework provides a solution to describe the input build parameters, flags,
macros, etc. in a structured way. It contains two utilities for this purpose:
* Map: simple key-value pair implementation.
* Group: collection of related maps.
The related parameters shall be packed into a group (or "setting group"). The
setting groups shall be defined and filled with content in config files.
Currently the config files are created and edited manually, but later a
configuration management tool (e.g. Kconfig) shall be used to generate these
files. Therefore, the framework does not contain parameter validation and
conflict checking, these shall be handled by the configuration tool.
Target description
^^^^^^^^^^^^^^^^^^
The framework provides an API called STGT ('simple target') to describe the
targets, i.e. what is the build output, what source files are used, what
libraries are linked, etc. The API wraps the CMake target functions, and also
extends the built-in functionality, it can use the setting groups described in
the previous section. A group can be applied onto a target, i.e. a collection of
macros, flags, etc. can be applied onto the given output executable/library.
This provides a more granular way than the current Makefile system where most of
these are global and applied onto each target.
Compiler abstraction
^^^^^^^^^^^^^^^^^^^^
Apart from the built-in CMake usage of the compiler, there are some common tasks
that CMake does not solve (e.g. preprocessing a file). For these tasks the
framework uses wrapper functions instead of direct calls to the compiler. This
way it is not tied to one specific compiler.
External tools
^^^^^^^^^^^^^^
In the TF-A buildsystem some external tools are used, e.g. fiptool for image
generation or dtc for device tree compilation. These tools have to be found
and/or built by the framework. For this, the CMake find_package functionality is
used, any other necessary tools can be added later.
Workflow
--------
The following diagram demonstrates the development workflow using the framework:
|Framework workflow|
The process can be split into two main phases:
In the provisioning phase, first we have to obtain the necessary resources, i.e.
clone the code repository and other dependencies. Next we have to do the
configuration, preferably using a config tool like KConfig.
In the development phase first we run CMake, which will generate the buildsystem
using the selected generator backend (currently only the Makefile generator is
supported). After this we run the selected build tool which in turn calls the
compiler, linker, packaging tool, etc. Finally we can run and debug the output
executables.
Usually during development only the steps in this second phase have to be
repeated, while the provisioning phase needs to be done only once (or rarely).
Example
-------
This is a short example for the basic framework usage.
First, we create a setting group called *mem_conf* and fill it with several
parameters. It is worth noting the difference between *CONFIG* and *DEFINE*
types: the former is only a CMake domain option, the latter is only a C language
macro.
Next, we create a target called *fw1* and add the *mem_conf* setting group to
it. This means that all source and header files used by the target will have all
the parameters declared in the setting group. Then we set the target type to
executable, and add some source files. Since the target has the parameters from
the settings group, we can use it for conditionally adding source files. E.g.
*dram_controller.c* will only be added if MEM_TYPE equals dram.
.. code-block:: cmake
group_new(NAME mem_conf)
group_add(NAME mem_conf TYPE DEFINE KEY MEM_SIZE VAL 1024)
group_add(NAME mem_conf TYPE CONFIG DEFINE KEY MEM_TYPE VAL dram)
group_add(NAME mem_conf TYPE CFLAG KEY -Os)
stgt_create(NAME fw1)
stgt_add_setting(NAME fw1 GROUPS mem_conf)
stgt_set_target(NAME fw1 TYPE exe)
stgt_add_src(NAME fw1 SRC
${CMAKE_SOURCE_DIR}/main.c
)
stgt_add_src_cond(NAME fw1 KEY MEM_TYPE VAL dram SRC
${CMAKE_SOURCE_DIR}/dram_controller.c
)
.. |Framework structure| image::
../resources/diagrams/cmake_framework_structure.png
:width: 75 %
.. |Framework workflow| image::
../resources/diagrams/cmake_framework_workflow.png
--------------
*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
@@ -0,0 +1,197 @@
Enhance Context Management library for EL3 firmware
===================================================
:Authors: Soby Mathew & Zelalem Aweke
:Organization: Arm Limited
:Contact: Soby Mathew <soby.mathew@arm.com> & Zelalem Aweke <zelalem.aweke@arm.com>
:Status: RFC
.. contents:: Table of Contents
Introduction
------------
The context management library in TF-A provides the basic CPU context
initialization and management routines for use by different components
in EL3 firmware. The original design of the library was done keeping in
mind the 2 world switch and hence this design pattern has been extended to
keep up with growing requirements of EL3 firmware. With the introduction
of a new Realm world and a separate Root world for EL3 firmware, it is clear
that this library needs to be refactored to cater for future enhancements and
reduce chances of introducing error in code. This also aligns with the overall
goal of reducing EL3 firmware complexity and footprint.
It is expected that the suggestions below could have legacy implications and
hence we are mainly targeting SPM/RMM based systems. It is expected that these
legacy issues will need to be sorted out as part of implementation on a case
by case basis.
Design Principles
-----------------
The below section lays down the design principles for re-factoring the context
management library :
(1) **Decentralized model for context mgmt**
Both the Secure and Realm worlds have associated dispatcher component in
EL3 firmware to allow management of their respective worlds. Allowing the
dispatcher to own the context for their respective world and moving away
from a centralized policy management by context management library will
remove the world differentiation code in the library. This also means that
the library will not be responsible for CPU feature enablement for
Secure and Realm worlds. See point 3 and 4 for more details.
The Non Secure world does not have a dispatcher component and hence EL3
firmware (BL31)/context management library needs to have routines to help
initialize the Non Secure world context.
(2) **EL3 should only initialize immediate used lower EL**
Due to the way TF-A evolved, from EL3 interacting with an S-EL1 payload to
SPM in S-EL2, there is some code initializing S-EL1 registers which is
probably redundant when SPM is present in S-EL2. As a principle, EL3
firmware should only initialize the next immediate lower EL in use.
If EL2 needs to be skipped and is not to be used at runtime, then
EL3 can do the bare minimal EL2 init and init EL1 to prepare for EL3 exit.
It is expected that this skip EL2 configuration is only needed for NS
world to support legacy Android deployments. It is worth removing this
`skip EL2 for Non Secure` config support if this is no longer used.
(3) **Maintain EL3 sysregs which affect lower EL within CPU context**
The CPU context contains some EL3 sysregs and gets applied on a per-world
basis (eg: cptr_el3, scr_el3, zcr_el3 is part of the context
because different settings need to be applied between each world).
But this design pattern is not enforced in TF-A. It is possible to directly
modify EL3 sysreg dynamically during the transition between NS and Secure
worlds. Having multiple ways of manipulating EL3 sysregs for different
values between the worlds is flaky and error prone. The proposal is to
enforce the rule that any EL3 sysreg which can be different between worlds
is maintained in the CPU Context. Once the context is initialized the
EL3 sysreg values corresponding to the world being entered will be restored.
(4) **Allow more flexibility for Dispatchers to select feature set to save and restore**
The current functions for EL2 CPU context save and restore is a single
function which takes care of saving and restoring all the registers for
EL2. This method is inflexible and it does not allow to dynamically detect
CPU features to select registers to save and restore. It also assumes that
both Realm and Secure world will have the same feature set enabled from
EL3 at runtime and makes it hard to enable different features for each
world. The framework should cater for selective save and restore of CPU
registers which can be controlled by the dispatcher.
For the implementation, this could mean that there is a separate assembly
save and restore routine corresponding to Arch feature. The memory allocation
within the CPU Context for each set of registers will be controlled by a
FEAT_xxx build option. It is a valid configuration to have
context memory allocated but not used at runtime based on feature detection
at runtime or the platform owner has decided not to enable the feature
for the particular world.
Context Allocation and Initialization
-------------------------------------
|context_mgmt_abs|
.. |context_mgmt_abs| image::
../resources/diagrams/context_management_abs.png
The above figure shows how the CPU context is allocated within TF-A. The
allocation for Secure and Realm world is by the respective dispatcher. In the case
of NS world, the context is allocated by the PSCI lib. This scheme allows TF-A
to be built in various configurations (with or without Secure/Realm worlds) and
will result in optimal memory footprint. The Secure and Realm world contexts are
initialized by invoking context management library APIs which then initialize
each world based on conditional evaluation of the security state of the
context. The proposal here is to move the conditional initialization
of context for Secure and Realm worlds to their respective dispatchers and
have the library do only the common init needed. The library can export
helpers to initialize registers corresponding to certain features but
should not try to do different initialization between the worlds. The library
can also export helpers for initialization of NS CPU Context since there is no
dispatcher for that world.
This implies that any world specific code in context mgmt lib should now be
migrated to the respective "owners". To maintain compatibility with legacy, the
current functions can be retained in the lib and perhaps define new ones for
use by SPMD and RMMD. The details of this can be worked out during
implementation.
Introducing Root Context
------------------------
Till now, we have been ignoring the fact that Root world (or EL3) itself could
have some settings which are distinct from NS/S/Realm worlds. In this case,
Root world itself would need to maintain some sysregs settings for its own
execution and would need to use sysregs of lower EL (eg: PAuth, pmcr) to enable
some functionalities in EL3. The current sequence for context save and restore
in TF-A is as given below:
|context_mgmt_existing|
.. |context_mgmt_existing| image::
../resources/diagrams/context_mgmt_existing.png
Note1: The EL3 CPU context is not a homogenous collection of EL3 sysregs but
a collection of EL3 and some other lower EL registers. The save and restore
is also not done homogenously but based on the objective of using the
particular register.
Note2: The EL1 context save and restore can possibly be removed when switching
to S-EL2 as SPM can take care of saving the incoming NS EL1 context.
It can be seen that the EL3 sysreg values applied while the execution is in Root
world corresponds to the world it came from (eg: if entering EL3 from NS world,
the sysregs correspond to the values in NS context). There is a case that EL3
itself may have some settings to apply for various reasons. A good example for
this is the cptr_el3 regsiter. Although FPU traps need to be disabled for
Non Secure, Secure and Realm worlds, the EL3 execution itself may keep the trap
enabled for the sake of robustness. Another example is, if the MTE feature
is enabled for a particular world, this feature will be enabled for Root world
as well when entering EL3 from that world. The firmware at EL3 may not
be expecting this feature to be enabled and may cause unwanted side-effects
which could be problematic. Thus it would be more robust if Root world is not
subject to EL3 sysreg values from other worlds but maintains its own values
which is stable and predictable throughout root world execution.
There is also the case that when EL3 would like to make use of some
Architectural feature(s) or do some security hardening, it might need
programming of some lower EL sysregs. For example, if EL3 needs to make
use of Pointer Authentication (PAuth) feature, it needs to program
its own PAuth Keys during execution at EL3. Hence EL3 needs its
own copy of PAuth registers which needs to be restored on every
entry to EL3. A similar case can be made for DIT bit in PSTATE,
or use of SP_EL0 for C Runtime Stack at EL3.
The proposal here is to maintain a separate root world CPU context
which gets applied for Root world execution. This is not the full
CPU_Context, but subset of EL3 sysregs (`el3_sysreg`) and lower EL
sysregs (`root_exc_context`) used by EL3. The save and restore
sequence for this Root context would need to be done in
an optimal way. The `el3_sysreg` does not need to be saved
on EL3 Exit and possibly only some registers in `root_exc_context`
of Root world context would need to be saved on EL3 exit (eg: SP_EL0).
The new sequence for world switch including Root world context would
be as given below :
|context_mgmt_proposed|
.. |context_mgmt_proposed| image::
../resources/diagrams/context_mgmt_proposed.png
Having this framework in place will allow Root world to make use of lower EL
registers easily for its own purposes and also have a fixed EL3 sysreg setting
which is not affected by the settings of other worlds. This will unify the
Root world register usage pattern for its own execution and remove some
of the adhoc usages in code.
Conclusion
----------
Of all the proposals, the introduction of Root world context would likely need
further prototyping to confirm the design and we will need to measure the
performance and memory impact of this change. Other changes are incremental
improvements which are thought to have negligible impact on EL3 performance.
--------------
*Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.*
@@ -0,0 +1,132 @@
DRTM Proof of Concept
=====================
Dynamic Root of Trust for Measurement (DRTM) begins a new trust environment
by measuring and executing a protected payload.
Static Root of Trust for Measurement (SRTM)/Measured Boot implementation,
currently used by TF-A covers all firmwares, from the boot ROM to the normal
world bootloader. As a whole, they make up the system's TCB. These boot
measurements allow attesting to what software is running on the system and
enable enforcing security policies.
As the boot chain grows or firmware becomes dynamically extensible,
establishing an attestable TCB becomes more challenging. DRTM provides a
solution to this problem by allowing measurement chains to be started at
any time. As these measurements are stored separately from the boot-time
measurements, they reduce the size of the TCB, which helps reduce the attack
surface and the risk of untrusted code executing, which could compromise
the security of the system.
Components
~~~~~~~~~~
- **DCE-Preamble**: The DCE Preamble prepares the platform for DRTM by
doing any needed configuration, loading the target payload image(DLME),
and preparing input parameters needed by DRTM. Finally, it invokes the
DL Event to start the dynamic launch.
- **D-CRTM**: The D-CRTM is the trust anchor (or root of trust) for the
DRTM boot sequence and is where the dynamic launch starts. The D-CRTM
must be implemented as a trusted agent in the system. The D-CRTM
initializes the TPM for DRTM and prepares the environment for the next
stage of DRTM, the DCE. The D-CRTM measures the DCE, verifies its
signature, and transfers control to it.
- **DCE**: The DCE executes on an application core. The DCE verifies the
systems state, measures security-critical attributes of the system,
prepares the memory region for the target payload, measures the payload,
and finally transfers control to the payload.
- **DLME**: The protected payload is referred to as the Dynamically Launched
Measured Environment, or DLME. The DLME begins execution in a safe state,
with a single thread of execution, DMA protections, and interrupts
disabled. The DCE provides data to the DLME that it can use to verify the
configuration of the system.
In this proof of concept, DCE and D-CRTM are implemented in BL31 and
DCE-Preamble and DLME are implemented in UEFI application. A DL Event is
triggered as a SMC by DCE-Preamble and handled by D-CRTM, which launches the
DLME via DCE.
This manual provides instructions to build TF-A code with pre-buit EDK2
and DRTM UEFI application.
Building the PoC for the Arm FVP platform
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(1) Use the below command to clone TF-A source code -
.. code:: shell
$ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
(2) There are prebuilt binaries required to execute the DRTM implementation
in the `prebuilts-drtm-bins`_.
Download EDK2 *FVP_AARCH64_EFI.fd* and UEFI DRTM application *test-disk.img*
binary from `prebuilts-drtm-bins`_.
(3) Build the TF-A code using below command
.. code:: shell
$ make CROSS_COMPILE=aarch64-none-elf- ARM_ROTPK_LOCATION=devel_rsa
DEBUG=1 V=1 BL33=</path/to/FVP_AARCH64_EFI.fd> DRTM_SUPPORT=1
MBEDTLS_DIR=</path/to/mbedTLS-source> USE_ROMLIB=1 all fip
Running DRTM UEFI application on the Armv8-A AEM FVP
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To run the DRTM test application along with DRTM implementation in BL31,
you need an FVP model. Please use the version of FVP_Base_RevC-2xAEMvA model
advertised in the TF-A documentation.
.. code:: shell
FVP_Base_RevC-2xAEMvA \
--data cluster0.cpu0=</path/to/romlib.bin>@0x03ff2000 \
--stat \
-C bp.flashloader0.fname=<path/to/fip.bin> \
-C bp.secureflashloader.fname=<path/to/bl1.bin> \
-C bp.ve_sysregs.exit_on_shutdown=1 \
-C bp.virtioblockdevice.image_path=<path/to/test-disk.img> \
-C cache_state_modelled=1 \
-C cluster0.check_memory_attributes=0 \
-C cluster0.cpu0.etm-present=0 \
-C cluster0.cpu1.etm-present=0 \
-C cluster0.cpu2.etm-present=0 \
-C cluster0.cpu3.etm-present=0 \
-C cluster0.stage12_tlb_size=1024 \
-C cluster1.check_memory_attributes=0 \
-C cluster1.cpu0.etm-present=0 \
-C cluster1.cpu1.etm-present=0 \
-C cluster1.cpu2.etm-present=0 \
-C cluster1.cpu3.etm-present=0 \
-C cluster1.stage12_tlb_size=1024 \
-C pctl.startup=0.0.0.0 \
-Q 1000 \
"$@"
The bottom of the output from *uart1* should look something like the
following to indicate that the last SMC to unprotect memory has been fired
successfully.
.. code-block:: shell
...
INFO: DRTM service handler: version
INFO: ++ DRTM service handler: TPM features
INFO: ++ DRTM service handler: Min. mem. requirement features
INFO: ++ DRTM service handler: DMA protection features
INFO: ++ DRTM service handler: Boot PE ID features
INFO: ++ DRTM service handler: TCB-hashes features
INFO: DRTM service handler: dynamic launch
WARNING: DRTM service handler: close locality is not supported
INFO: DRTM service handler: unprotect mem
--------------
*Copyright (c) 2022, Arm Limited. All rights reserved.*
.. _prebuilts-drtm-bins: https://downloads.trustedfirmware.org/tf-a/drtm
.. _DRTM-specification: https://developer.arm.com/documentation/den0113/a
@@ -0,0 +1,15 @@
Design Documents
================
.. toctree::
:maxdepth: 1
:caption: Contents
cmake_framework
context_mgmt_rework
measured_boot_poc
drtm_poc
--------------
*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.*
@@ -0,0 +1,507 @@
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: ``<fvp-project>/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 ``<toolkit_home>/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/