diff options
Diffstat (limited to '')
-rw-r--r-- | docs/design_documents/cmake_framework.rst | 165 | ||||
-rw-r--r-- | docs/design_documents/context_mgmt_rework.rst | 197 | ||||
-rw-r--r-- | docs/design_documents/drtm_poc.rst | 132 | ||||
-rw-r--r-- | docs/design_documents/index.rst | 18 | ||||
-rw-r--r-- | docs/design_documents/measured_boot.rst | 234 | ||||
-rw-r--r-- | docs/design_documents/measured_boot_poc.rst | 509 | ||||
-rw-r--r-- | docs/design_documents/psci_osi_mode.rst | 718 | ||||
-rw-r--r-- | docs/design_documents/rss.rst | 690 |
8 files changed, 2663 insertions, 0 deletions
diff --git a/docs/design_documents/cmake_framework.rst b/docs/design_documents/cmake_framework.rst new file mode 100644 index 0000000..d88942e --- /dev/null +++ b/docs/design_documents/cmake_framework.rst @@ -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.* diff --git a/docs/design_documents/context_mgmt_rework.rst b/docs/design_documents/context_mgmt_rework.rst new file mode 100644 index 0000000..59f9d4e --- /dev/null +++ b/docs/design_documents/context_mgmt_rework.rst @@ -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.* diff --git a/docs/design_documents/drtm_poc.rst b/docs/design_documents/drtm_poc.rst new file mode 100644 index 0000000..79e1142 --- /dev/null +++ b/docs/design_documents/drtm_poc.rst @@ -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 + system’s 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 diff --git a/docs/design_documents/index.rst b/docs/design_documents/index.rst new file mode 100644 index 0000000..ecc68b2 --- /dev/null +++ b/docs/design_documents/index.rst @@ -0,0 +1,18 @@ +Design Documents +================ + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + cmake_framework + context_mgmt_rework + measured_boot_poc + drtm_poc + rss + psci_osi_mode + measured_boot + +-------------- + +*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/design_documents/measured_boot.rst b/docs/design_documents/measured_boot.rst new file mode 100644 index 0000000..c4e5213 --- /dev/null +++ b/docs/design_documents/measured_boot.rst @@ -0,0 +1,234 @@ +Measured Boot Design +==================== + +This document briefly explains the Measured-Boot design implementation +in |TF-A|. + +Introduction +------------ + +Measured Boot is the process of computing and securely recording hashes of code +and critical data at each stage in the boot chain before the code/data is used. + +These measurements can be leveraged by other components in the system to +implement a complete attestation system. For example, they could be used to +enforce local attestation policies (such as releasing certain platform keys or +not), or they could be securely sent to a remote challenger a.k.a. `verifier` +after boot to attest to the state of the code and critical-data. + +Measured Boot does not authenticate the code or critical-data, but simply +records what code/critical-data was present on the system during boot. + +It is assumed that BL1 is implicitly trusted (by virtue of immutability) and +acts as the root of trust for measurement hence it is not measured. + +The Measured Boot implementation in TF-A supports multiple backends to securely +store measurements mentioned below in the :ref:`Measured Boot Backends` section. + +Critical data +------------- + +All firmware images - i.e. BLx images and their corresponding configuration +files, if any - must be measured. In addition to that, there might be specific +pieces of data which needs to be measured as well. These are typically different +on each platform. They are referred to as *critical data*. + +Critical data for the platform can be determined using the following criteria: + +#. Data that influence boot flow behaviour such as - + + - Configuration parameters that alter the boot flow path. + - Parameters that determine which firmware to load from NV-Storage to + SRAM/DRAM to pass the boot process successfully. + +#. Hardware configurations settings, debug settings and security policies + that need to be in a valid state for a device to maintain its security + posture during boot and runtime. +#. Security-sensitive data that is being updated by hardware. + +Examples of Critical data: + +#. The list of errata workarounds being applied at reset. +#. State of fuses such as whether an SoC is in secure mode. +#. NV counters that determine whether firmware is up-to-date and secure. + +Measurement slot +---------------- + +The measurement slot resides in a Trusted Module and can be either a secure +register or memory. +The measurement slot is used to provide a method to cryptographically record +(measure) images and critical data on a platform. +The measurement slot update calculation, called an **extend** operation, is +a one-way hash of all the previous measurements and the new measurement. It +is the only way to change the slot value, thus no measurements can ever be +removed or overwritten. + +.. _Measured Boot Backends: + +Measured Boot Backends +---------------------- + +The Measured Boot implementation in TF-A supports: + +#. Event Log + + The TCG Event Log holds a record of measurements made into the Measurement + Slot aka PCR (Platform Configuration Register). + + The `TCG EFI Protocol Specification`_ provides details on how to measure + components. The Arm document + `Arm® Server Base Security Guide`_ provides specific guidance for + measurements on an SBSA/SBBR server system. By considering these + specifications it is decided that - + + #. Use PCR0 for images measurements. + #. Use PCR1 for Critical data measurements. + + TCG has specified the architecture for the structure of this log in the + `TCG EFI Protocol Specification`_. The specification describes two event + log event records—the legacy, fixed size SHA1 structure called TCG_PCR_EVENT + and the variable length crypto agile structure called TCG_PCR_EVENT2. Event + Log driver implemented in TF-A covers later part. + +#. RSS + + It is one of physical backend to extend the measurements. Please refer this + document :ref:`Runtime Security Subsystem (RSS)` for more details. + +Platform Interface +------------------ + +Every image which gets successfully loaded in memory (and authenticated, if +trusted boot is enabled) then gets measured. In addition to that, platforms +can measure any relevant piece of critical data at any point during the boot. +The following diagram outlines the call sequence for Measured Boot platform +interfaces invoked from generic code: + +.. image:: ../resources/diagrams/measured_boot_design.png + +These platform interfaces are used by BL1 and BL2 only, and are declared in +``include/plat/common/platform.h``. +BL31 does not load and thus does not measure any image. + +Responsibilities of these platform interfaces are - + +#. **Function : blx_plat_mboot_init()** + + .. code-block:: c + + void bl1_plat_mboot_init(void); + void bl2_plat_mboot_init(void); + + Initialise all Measured Boot backends supported by the platform + (e.g. Event Log buffer, RSS). As these functions do not return any value, + the platform should deal with error management, such as logging the error + somewhere, or panicking the system if this is considered a fatal error. + + - On the Arm FVP port - + + - In BL1, this function is used to initialize the Event Log backend + driver, and also to write header information in the Event Log + buffer. + - In BL2, this function is used to initialize the Event Log buffer with + the information received from the BL1. It results in panic on + error. + +#. **Function : plat_mboot_measure_image()** + + .. code-block:: c + + int plat_mboot_measure_image(unsigned int image_id, + image_info_t *image_data); + + - Measure the image using a hash function of the crypto module. + + - Record the measurement in the corresponding backend - + + - If it is Event Log backend, then record the measurement in TCG Event Log + format. + - If it is a secure crypto-processor (like RSS), then extend the designated + PCR (or slot) with the given measurement. + - This function must return 0 on success, a signed integer error code + otherwise. + - On the Arm FVP port, this function measures the given image and then + records that measurement in the Event Log buffer. + The passed id is used to retrieve information about on how to measure + the image (e.g. PCR number). + +#. **Function : blx_plat_mboot_finish()** + + .. code-block:: c + + void bl1_plat_mboot_finish(void); + void bl2_plat_mboot_finish(void); + + - Do all teardown operations with respect to initialised Measured Boot backends. + This could be - + + - Pass the Event Log details (start address and size) to Normal world or to + Secure World using any platform implementation way. + - Measure all critical data if any. + - As these functions do not return any value, the platform should deal with + error management, such as logging the error somewhere, or panicking the + system if this is considered a fatal error. + + - On the Arm FVP port - + + - In BL1, this function is used to pass the base address of + the Event Log buffer and its size to BL2 via tb_fw_config to extend the + Event Log buffer with the measurement of various images loaded by BL2. + It results in panic on error. + - In BL2, this function is used to pass the Event Log buffer information + (base address and size) to non-secure(BL33) and trusted OS(BL32) via + nt_fw and tos_fw config respectively. + See :ref:`DTB binding for Event Log properties` for a description of the + bindings used for Event Log properties. + +#. **Function : plat_mboot_measure_critical_data()** + + .. code-block:: c + + int plat_mboot_measure_critical_data(unsigned int critical_data_id, + const void *base, + size_t size); + + This interface is not invoked by the generic code and it is up to the + platform layer to call it where appropriate. + + This function measures the given critical data structure and records its + measurement using the Measured Boot backend driver. + This function must return 0 on success, a signed integer error code + otherwise. + + In FVP, Non volatile counters get measured and recorded as Critical data + using the backend via this interface. + +#. **Function : plat_mboot_measure_key()** + + .. code-block:: c + + int plat_mboot_measure_key(const void *pk_oid, const void *pk_ptr, + size_t pk_len); + + - This function is used by the platform to measure the passed key and + publicise it using any of the supported backends. + - The authentication module within the trusted boot framework calls this + function for every ROTPK involved in verifying the signature of a root + certificate and for every subsidiary key that gets extracted from a key + certificate for later authentication of a content certificate. + - A cookie, passed as the first argument, serves as a key-OID pointer + associated with the public key data, passed as the second argument. + - Public key data size is passed as the third argument to this function. + - This function must return 0 on success, a signed integer error code + otherwise. + - In FVP platform, this function is used to calculate the hash of the given + key and forward this hash to RSS alongside the measurement of the image + which the key signs. + +-------------- + +*Copyright (c) 2023, Arm Limited. All rights reserved.* + +.. _Arm® Server Base Security Guide: https://developer.arm.com/documentation/den0086/latest +.. _TCG EFI Protocol Specification: https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf diff --git a/docs/design_documents/measured_boot_poc.rst b/docs/design_documents/measured_boot_poc.rst new file mode 100644 index 0000000..86cf4d1 --- /dev/null +++ b/docs/design_documents/measured_boot_poc.rst @@ -0,0 +1,509 @@ +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 |TF-A| supports several +backends and each has a different means to store the measurements. +This section focuses on the `TCG event log`_ backend, which stores measurements +in secure memory. + +See details of :ref:`Measured Boot Design`. + +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 instructions 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 following build options: + + .. code:: shell + + $ MEASURED_BOOT=y MEASURED_BOOT_FTPM=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-2023, 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 +.. _TCG event log: https://trustedcomputinggroup.org/resource/tcg-efi-platform-specification/ diff --git a/docs/design_documents/psci_osi_mode.rst b/docs/design_documents/psci_osi_mode.rst new file mode 100644 index 0000000..a6e1bdf --- /dev/null +++ b/docs/design_documents/psci_osi_mode.rst @@ -0,0 +1,718 @@ +PSCI OS-initiated mode +====================== + +:Author: Maulik Shah & Wing Li +:Organization: Qualcomm Innovation Center, Inc. & Google LLC +:Contact: Maulik Shah <quic_mkshah@quicinc.com> & Wing Li <wingers@google.com> +:Status: Accepted + +.. contents:: Table of Contents + +Introduction +------------ + +Power state coordination +^^^^^^^^^^^^^^^^^^^^^^^^ + +A power domain topology is a logical hierarchy of power domains in a system that +arises from the physical dependencies between power domains. + +Local power states describe power states for an individual node, and composite +power states describe the combined power states for an individual node and its +parent node(s). + +Entry into low-power states for a topology node above the core level requires +coordinating its children nodes. For example, in a system with a power domain +that encompasses a shared cache, and a separate power domain for each core that +uses the shared cache, the core power domains must be powered down before the +shared cache power domain can be powered down. + +PSCI supports two modes of power state coordination: platform-coordinated and +OS-initiated. + +Platform-coordinated +~~~~~~~~~~~~~~~~~~~~ + +Platform-coordinated mode is the default mode of power state coordination, and +is currently the only supported mode in TF-A. + +In platform-coordinated mode, the platform is responsible for coordinating power +states, and chooses the deepest power state for a topology node that can be +tolerated by its children. + +OS-initiated +~~~~~~~~~~~~ + +OS-initiated mode is optional. + +In OS-initiated mode, the calling OS is responsible for coordinating power +states, and may request for a topology node to enter a low-power state when +its last child enters the low-power state. + +Motivation +---------- + +There are two reasons why OS-initiated mode might be a more suitable option than +platform-coordinated mode for a platform. + +Scalability +^^^^^^^^^^^ + +In platform-coordinated mode, each core independently selects their own local +power states, and doesn't account for composite power states that are shared +between cores. + +In OS-initiated mode, the OS has knowledge of the next wakeup event for each +core, and can have more precise control over the entry, exit, and wakeup +latencies when deciding if a composite power state (e.g. for a cluster) is +appropriate. This is especially important for multi-cluster SMP systems and +heterogeneous systems like big.LITTLE, where different processor types can have +different power efficiencies. + +Simplicity +^^^^^^^^^^ + +In platform-coordinated mode, the OS doesn't have visibility when the last core +at a power level enters a low-power state. If the OS wants to perform last man +activity (e.g. powering off a shared resource when it is no longer needed), it +would have to communicate with an API side channel to know when it can do so. +This could result in a design smell where the platform is using +platform-coordinated mode when it should be using OS-initiated mode instead. + +In OS-initiated mode, the OS can perform last man activity if it selects a +composite power state when the last core enters a low-power state. This +eliminates the need for a side channel, and uses the well documented API between +the OS and the platform. + +Current vendor implementations and workarounds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* STMicroelectronics + + * For their ARM32 platforms, they're using OS-initiated mode implemented in + OP-TEE. + * For their future ARM64 platforms, they are interested in using OS-initiated + mode in TF-A. + +* Qualcomm + + * For their mobile platforms, they're using OS-initiated mode implemented in + their own custom secure monitor firmware. + * For their Chrome OS platforms, they're using platform-coordinated mode in + TF-A with custom driver logic to perform last man activity. + +* Google + + * They're using platform-coordinated mode in TF-A with custom driver logic to + perform last man activity. + +Both Qualcomm and Google would like to be able to use OS-initiated mode in TF-A +in order to simplify custom driver logic. + +Requirements +------------ + +PSCI_FEATURES +^^^^^^^^^^^^^ + +PSCI_FEATURES is for checking whether or not a PSCI function is implemented and +what its properties are. + +.. c:macro:: PSCI_FEATURES + + :param func_id: 0x8400_000A. + :param psci_func_id: the function ID of a PSCI function. + :retval NOT_SUPPORTED: if the function is not implemented. + :retval feature flags associated with the function: if the function is + implemented. + +CPU_SUSPEND feature flags +~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Reserved, bits[31:2] +* Power state parameter format, bit[1] + + * A value of 0 indicates the original format is used. + * A value of 1 indicates the extended format is used. + +* OS-initiated mode, bit[0] + + * A value of 0 indicates OS-initiated mode is not supported. + * A value of 1 indicates OS-initiated mode is supported. + +See sections 5.1.14 and 5.15 of the PSCI spec (DEN0022D.b) for more details. + +PSCI_SET_SUSPEND_MODE +^^^^^^^^^^^^^^^^^^^^^ + +PSCI_SET_SUSPEND_MODE is for switching between the two different modes of power +state coordination. + +.. c:macro:: PSCI_SET_SUSPEND_MODE + + :param func_id: 0x8400_000F. + :param mode: 0 indicates platform-coordinated mode, 1 indicates OS-initiated + mode. + :retval SUCCESS: if the request is successful. + :retval NOT_SUPPORTED: if OS-initiated mode is not supported. + :retval INVALID_PARAMETERS: if the requested mode is not a valid value (0 or + 1). + :retval DENIED: if the cores are not in the correct state. + +Switching from platform-coordinated to OS-initiated is only allowed if the +following conditions are met: + +* All cores are in one of the following states: + + * Running. + * Off, through a call to CPU_OFF or not yet booted. + * Suspended, through a call to CPU_DEFAULT_SUSPEND. + +* None of the cores has called CPU_SUSPEND since the last change of mode or + boot. + +Switching from OS-initiated to platform-coordinated is only allowed if all cores +other than the calling core are off, either through a call to CPU_OFF or not yet +booted. + +If these conditions are not met, the PSCI implementation must return DENIED. + +See sections 5.1.19 and 5.20 of the PSCI spec (DEN0022D.b) for more details. + +CPU_SUSPEND +^^^^^^^^^^^ + +CPU_SUSPEND is for moving a topology node into a low-power state. + +.. c:macro:: CPU_SUSPEND + + :param func_id: 0xC400_0001. + :param power_state: the requested low-power state to enter. + :param entry_point_address: the address at which the core must resume + execution following wakeup from a powerdown state. + :param context_id: this field specifies a pointer to the saved context that + must be restored on a core following wakeup from a powerdown state. + :retval SUCCESS: if the request is successful. + :retval INVALID_PARAMETERS: in OS-initiated mode, this error is returned when + a low-power state is requested for a topology node above the core level, + and at least one of the node's children is in a local low-power state + that is incompatible with the request. + :retval INVALID_ADDRESS: if the entry_point_address argument is invalid. + :retval DENIED: only in OS-initiated mode; this error is returned when a + low-power state is requested for a topology node above the core level, + and at least one of the node's children is running, i.e. not in a + low-power state. + +In platform-coordinated mode, the PSCI implementation coordinates requests from +all cores to determine the deepest power state to enter. + +In OS-initiated mode, the calling OS is making an explicit request for a +specific power state, as opposed to expressing a vote. The PSCI implementation +must comply with the request, unless the request is not consistent with the +implementation's view of the system's state, in which case, the implementation +must return INVALID_PARAMETERS or DENIED. + +See sections 5.1.2 and 5.4 of the PSCI spec (DEN0022D.b) for more details. + +Power state formats +~~~~~~~~~~~~~~~~~~~ + +Original format + +* Power Level, bits[25:24] + + * The requested level in the power domain topology to enter a low-power + state. + +* State Type, bit[16] + + * A value of 0 indicates a standby or retention state. + * A value of 1 indicates a powerdown state. + +* State ID, bits[15:0] + + * Field to specify the requested composite power state. + * The state ID encodings must uniquely describe every possible composite + power state. + * In OS-initiated mode, the state ID encoding must allow expressing the + power level at which the calling core is the last to enter a powerdown + state. + +Extended format + +* State Type, bit[30] +* State ID, bits[27:0] + +Races in OS-initiated mode +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In OS-initiated mode, there are race windows where the OS's view and +implementation's view of the system's state differ. It is possible for the OS to +make requests that are invalid given the implementation's view of the system's +state. For example, the OS might request a powerdown state for a node from one +core, while at the same time, the implementation observes that another core in +that node is powering up. + +To address potential race conditions in power state requests: + +* The calling OS must specify in each CPU_SUSPEND request the deepest power + level for which it sees the calling core as the last running core (last man). + This is required even if the OS doesn't want the node at that power level to + enter a low-power state. +* The implementation must validate that the requested power states in the + CPU_SUSPEND request are consistent with the system's state, and that the + calling core is the last core running at the requested power level, or deny + the request otherwise. + +See sections 4.2.3.2, 6.2, and 6.3 of the PSCI spec (DEN0022D.b) for more +details. + +Caveats +------- + +CPU_OFF +^^^^^^^ + +CPU_OFF is always platform-coordinated, regardless of whether the power state +coordination mode for suspend is platform-coordinated or OS-initiated. If all +cores in a topology node call CPU_OFF, the last core will power down the node. + +In OS-initiated mode, if a subset of the cores in a topology node has called +CPU_OFF, the last running core may call CPU_SUSPEND to request a powerdown state +at or above that node's power level. + +See section 5.5.2 of the PSCI spec (DEN0022D.b) for more details. + +Implementation +-------------- + +Current implementation of platform-coordinated mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Platform-coordinated is currently the only supported power state coordination +mode in TF-A. + +The functions of interest in the ``psci_cpu_suspend`` call stack are as follows: + +* ``psci_validate_power_state`` + + * This function calls a platform specific ``validate_power_state`` handler, + which takes the ``power_state`` parameter, and updates the ``state_info`` + object with the requested states for each power level. + +* ``psci_find_target_suspend_lvl`` + + * This function takes the ``state_info`` object containing the requested power + states for each power level, and returns the deepest power level that was + requested to enter a low power state, i.e. the target power level. + +* ``psci_do_state_coordination`` + + * This function takes the target power level and the ``state_info`` object + containing the requested power states for each power level, and updates the + ``state_info`` object with the coordinated target power state for each + level. + +* ``pwr_domain_suspend`` + + * This is a platform specific handler that takes the ``state_info`` object + containing the target power states for each power level, and transitions + each power level to the specified power state. + +Proposed implementation of OS-initiated mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To add support for OS-initiated mode, the following changes are proposed: + +* Add a boolean build option ``PSCI_OS_INIT_MODE`` for a platform to enable + optional support for PSCI OS-initiated mode. This build option defaults to 0. + +.. note:: + + If ``PSCI_OS_INIT_MODE=0``, the following changes will not be compiled into + the build. + +* Update ``psci_features`` to return 1 in bit[0] to indicate support for + OS-initiated mode for CPU_SUSPEND. +* Define a ``suspend_mode`` enum: ``PLAT_COORD`` and ``OS_INIT``. +* Define a ``psci_suspend_mode`` global variable with a default value of + ``PLAT_COORD``. +* Implement a new function handler ``psci_set_suspend_mode`` for + PSCI_SET_SUSPEND_MODE. +* Since ``psci_validate_power_state`` calls a platform specific + ``validate_power_state`` handler, the platform implementation should populate + the ``state_info`` object based on the state ID from the given ``power_state`` + parameter. +* ``psci_find_target_suspend_lvl`` remains unchanged. +* Implement a new function ``psci_validate_state_coordination`` that ensures the + request satisfies the following conditions, and denies any requests + that don't: + + * The requested power states for each power level are consistent with the + system's state + * The calling core is the last core running at the requested power level + + This function differs from ``psci_do_state_coordination`` in that: + + * The ``psci_req_local_pwr_states`` map is not modified if the request were to + be denied + * The ``state_info`` argument is never modified since it contains the power + states requested by the calling OS + +* Update ``psci_cpu_suspend_start`` to do the following: + + * If ``PSCI_SUSPEND_MODE`` is ``PLAT_COORD``, call + ``psci_do_state_coordination``. + * If ``PSCI_SUSPEND_MODE`` is ``OS_INIT``, call + ``psci_validate_state_coordination``. If validation fails, propagate the + error up the call stack. + +* Add a new optional member ``pwr_domain_validate_suspend`` to + ``plat_psci_ops_t`` to allow the platform to optionally perform validations + based on hardware states. + +* The platform specific ``pwr_domain_suspend`` handler remains unchanged. + +.. image:: ../resources/diagrams/psci-osi-mode.png + +Testing +------- + +The proposed patches can be found at +https://review.trustedfirmware.org/q/topic:psci-osi. + +Testing on FVP and Google platforms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The proposed patches add a new CPU Suspend in OSI mode test suite to TF-A Tests. +This has been enabled and verified on the FVP_Base_RevC-2xAEMvA platform and +Google platforms, and excluded from all other platforms via the build option +``PLAT_TESTS_SKIP_LIST``. + +Testing on STM32MP15 +^^^^^^^^^^^^^^^^^^^^ + +The proposed patches have been tested and verified on the STM32MP15 platform, +which has a single cluster with 2 CPUs, by Gabriel Fernandez +<gabriel.fernandez@st.com> from STMicroelectronics with this device tree +configuration: + +.. code-block:: devicetree + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0>; + enable-method = "psci"; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; + }; + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <1>; + enable-method = "psci"; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; + }; + + idle-states { + cpu_retention: cpu-retention { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x00000001>; + entry-latency-us = <130>; + exit-latency-us = <620>; + min-residency-us = <700>; + local-timer-stop; + }; + }; + + domain-idle-states { + CLUSTER_STOP: core-power-domain { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x01000001>; + entry-latency-us = <230>; + exit-latency-us = <720>; + min-residency-us = <2000>; + local-timer-stop; + }; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + CPU_PD0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&pd_core>; + domain-idle-states = <&cpu_retention>; + }; + + CPU_PD1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&pd_core>; + domain-idle-states = <&cpu_retention>; + }; + + pd_core: power-domain-cluster { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_STOP>; + }; + }; + +Testing on Qualcomm SC7280 +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The proposed patches have been tested and verified on the SC7280 platform by +Maulik Shah <quic_mkshah@quicinc.com> from Qualcomm with this device tree +configuration: + +.. code-block:: devicetree + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x0>; + enable-method = "psci"; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; + }; + + CPU1: cpu@100 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x100>; + enable-method = "psci"; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; + }; + + CPU2: cpu@200 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x200>; + enable-method = "psci"; + power-domains = <&CPU_PD2>; + power-domain-names = "psci"; + }; + + CPU3: cpu@300 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x300>; + enable-method = "psci"; + power-domains = <&CPU_PD3>; + power-domain-names = "psci"; + } + + CPU4: cpu@400 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x400>; + enable-method = "psci"; + power-domains = <&CPU_PD4>; + power-domain-names = "psci"; + }; + + CPU5: cpu@500 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x500>; + enable-method = "psci"; + power-domains = <&CPU_PD5>; + power-domain-names = "psci"; + }; + + CPU6: cpu@600 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x600>; + enable-method = "psci"; + power-domains = <&CPU_PD6>; + power-domain-names = "psci"; + }; + + CPU7: cpu@700 { + device_type = "cpu"; + compatible = "arm,kryo"; + reg = <0x0 0x700>; + enable-method = "psci"; + power-domains = <&CPU_PD7>; + power-domain-names = "psci"; + }; + + idle-states { + entry-method = "psci"; + + LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + idle-state-name = "little-power-down"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <549>; + exit-latency-us = <901>; + min-residency-us = <1774>; + local-timer-stop; + }; + + LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 { + compatible = "arm,idle-state"; + idle-state-name = "little-rail-power-down"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <702>; + exit-latency-us = <915>; + min-residency-us = <4001>; + local-timer-stop; + }; + + BIG_CPU_SLEEP_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + idle-state-name = "big-power-down"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <523>; + exit-latency-us = <1244>; + min-residency-us = <2207>; + local-timer-stop; + }; + + BIG_CPU_SLEEP_1: cpu-sleep-1-1 { + compatible = "arm,idle-state"; + idle-state-name = "big-rail-power-down"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <526>; + exit-latency-us = <1854>; + min-residency-us = <5555>; + local-timer-stop; + }; + }; + + domain-idle-states { + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + idle-state-name = "cluster-power-down"; + arm,psci-suspend-param = <0x40003444>; + entry-latency-us = <3263>; + exit-latency-us = <6562>; + min-residency-us = <9926>; + local-timer-stop; + }; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + CPU_PD0: cpu0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD1: cpu1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD2: cpu2 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD3: cpu3 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD4: cpu4 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; + }; + + CPU_PD5: cpu5 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; + }; + + CPU_PD6: cpu6 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; + }; + + CPU_PD7: cpu7 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; + }; + + CLUSTER_PD: cpu-cluster0 { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_SLEEP_0>; + }; + }; + +Comparisons on Qualcomm SC7280 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +CPUIdle states +~~~~~~~~~~~~~~ + +* 8 CPUs, 1 L3 cache +* Platform-coordinated mode + + * CPUIdle states + + * State0 - WFI + * State1 - Core collapse + * State2 - Rail collapse + * State3 - L3 cache off and system resources voted off + +* OS-initiated mode + + * CPUIdle states + + * State0 - WFI + * State1 - Core collapse + * State2 - Rail collapse + + * Cluster domain idle state + + * State3 - L3 cache off and system resources voted off + +.. image:: ../resources/diagrams/psci-flattened-vs-hierarchical-idle-states.png + +Results +~~~~~~~ + +* The following stats have been captured with fixed CPU frequencies from the use + case of 10 seconds of device idle with the display turned on and Wi-Fi and + modem turned off. +* Count refers to the number of times a CPU or cluster entered power collapse. +* Residency refers to the time in seconds a CPU or cluster stayed in power + collapse. +* The results are an average of 3 iterations of actual counts and residencies. + +.. image:: ../resources/diagrams/psci-pc-mode-vs-osi-mode.png + +OS-initiated mode was able to scale better than platform-coordinated mode for +multiple CPUs. The count and residency results for state3 (i.e. a cluster domain +idle state) in OS-initiated mode for multiple CPUs were much closer to the +results for a single CPU than in platform-coordinated mode. + +-------------- + +*Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/design_documents/rss.rst b/docs/design_documents/rss.rst new file mode 100644 index 0000000..18d5436 --- /dev/null +++ b/docs/design_documents/rss.rst @@ -0,0 +1,690 @@ +Runtime Security Subsystem (RSS) +================================ + +This document focuses on the relationship between the Runtime Security Subsystem +(RSS) and the application processor (AP). According to the ARM reference design +the RSS is an independent core next to the AP and the SCP on the same die. It +provides fundamental security guarantees and runtime services for the rest of +the system (e.g.: trusted boot, measured boot, platform attestation, +key management, and key derivation). + +At power up RSS boots first from its private ROM code. It validates and loads +its own images and the initial images of SCP and AP. When AP and SCP are +released from reset and their initial code is loaded then they continue their +own boot process, which is the same as on non-RSS systems. Please refer to the +``RSS documentation`` [1]_ for more details about the RSS boot flow. + +The last stage of the RSS firmware is a persistent, runtime component. Much +like AP_BL31, this is a passive entity which has no periodical task to do and +just waits for external requests from other subsystems. RSS and other +subsystems can communicate with each other over message exchange. RSS waits +in idle for the incoming request, handles them, and sends a response then goes +back to idle. + +RSS communication layer +----------------------- + +The communication between RSS and other subsystems are primarily relying on the +Message Handling Unit (MHU) module. The number of MHU interfaces between RSS +and other cores is IMPDEF. Besides MHU other modules also could take part in +the communication. RSS is capable of mapping the AP memory to its address space. +Thereby either RSS core itself or a DMA engine if it is present, can move the +data between memory belonging to RSS or AP. In this way, a bigger amount of data +can be transferred in a short time. + +The MHU comes in pairs. There is a sender and receiver side. They are connected +to each other. An MHU interface consists of two pairs of MHUs, one sender and +one receiver on both sides. Bidirectional communication is possible over an +interface. One pair provides message sending from AP to RSS and the other pair +from RSS to AP. The sender and receiver are connected via channels. There is an +IMPDEF number of channels (e.g: 4-16) between a sender and a receiver module. + +The RSS communication layer provides two ways for message exchange: + +- ``Embedded messaging``: The full message, including header and payload, are + exchanged over the MHU channels. A channel is capable of delivering a single + word. The sender writes the data to the channel register on its side and the + receiver can read the data from the channel on the other side. One dedicated + channel is used for signalling. It does not deliver any payload it is just + meant for signalling that the sender loaded the data to the channel registers + so the receiver can read them. The receiver uses the same channel to signal + that data was read. Signalling happens via IRQ. If the message is longer than + the data fit to the channel registers then the message is sent over in + multiple rounds. Both, sender and receiver allocate a local buffer for the + messages. Data is copied from/to these buffers to/from the channel registers. +- ``Pointer-access messaging``: The message header and the payload are + separated and they are conveyed in different ways. The header is sent + over the channels, similar to the embedded messaging but the payload is + copied over by RSS core (or by DMA) between the sender and the receiver. This + could be useful in the case of long messages because transaction time is less + compared to the embedded messaging mode. Small payloads are copied by the RSS + core because setting up DMA would require more CPU cycles. The payload is + either copied into an internal buffer or directly read-written by RSS. Actual + behavior depends on RSS setup, whether the partition supports memory-mapped + ``iovec``. Therefore, the sender must handle both cases and prevent access to + the memory, where payload data lives, while the RSS handles the request. + +The RSS communication layer supports both ways of messaging in parallel. It is +decided at runtime based on the message size which way to transfer the message. + +.. code-block:: bash + + +----------------------------------------------+ +-------------------+ + | | | | + | AP | | | + | | +--->| SRAM | + +----------------------------------------------| | | | + | BL1 / BL2 / BL31 | | | | + +----------------------------------------------+ | +-------------------+ + | ^ | ^ ^ + | send IRQ | receive |direct | | + V | |access | | + +--------------------+ +--------------------+ | | | + | MHU sender | | MHU receiver | | | Copy data | + +--------------------+ +--------------------+ | | | + | | | | | | | | | | | + | | channels | | | | channels | | | | | + | | e.g: 4-16 | | | | e.g: 4-16 | | | V | + +--------------------+ +--------------------+ | +-------+ | + | MHU receiver | | MHU sender | | +->| DMA | | + +--------------------+ +--------------------+ | | +-------+ | + | ^ | | ^ | + IRQ | receive | send | | | Copy data | + V | | | V V + +----------------------------------------------+ | | +-------------------+ + | |--+-+ | | + | RSS | | SRAM | + | | | | + +----------------------------------------------+ +-------------------+ + +.. Note:: + + The RSS communication layer is not prepared for concurrent execution. The + current use case only requires message exchange during the boot phase. In + the boot phase, only a single core is running and the rest of the cores are + in reset. + +Message structure +^^^^^^^^^^^^^^^^^ +A description of the message format can be found in the ``RSS communication +design`` [2]_ document. + +Source files +^^^^^^^^^^^^ +- RSS comms: ``drivers/arm/rss`` +- MHU driver: ``drivers/arm/mhu`` + + +API for communication over MHU +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The API is defined in these header files: + +- ``include/drivers/arm/rss_comms.h`` +- ``include/drivers/arm/mhu.h`` + +RSS provided runtime services +----------------------------- + +RSS provides the following runtime services: + +- ``Measured boot``: Securely store the firmware measurements which were + computed during the boot process and the associated metadata (image + description, measurement algorithm, etc.). More info on measured boot service + in RSS can be found in the ``measured_boot_integration_guide`` [3]_ . +- ``Delegated attestation``: Query the platform attestation token and derive a + delegated attestation key. More info on the delegated attestation service + in RSS can be found in the ``delegated_attestation_integration_guide`` [4]_ . +- ``OTP assets management``: Public keys used by AP during the trusted boot + process can be requested from RSS. Furthermore, AP can request RSS to + increase a non-volatile counter. Please refer to the + ``RSS key management`` [5]_ document for more details. + +Runtime service API +^^^^^^^^^^^^^^^^^^^ +The RSS provided runtime services implement a PSA aligned API. The parameter +encoding follows the PSA client protocol described in the +``Firmware Framework for M`` [6]_ document in chapter 4.4. The implementation is +restricted to the static handle use case therefore only the ``psa_call`` API is +implemented. + + +Software and API layers +^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + +----------------+ +---------------------+ + | BL1 / BL2 | | BL31 | + +----------------+ +---------------------+ + | | + | extend_measurement() | get_delegated_key() + | | get_platform_token() + V V + +----------------+ +---------------------+ + | PSA protocol | | PSA protocol | + +----------------+ +---------------------+ + | | + | psa_call() | psa_call() + | | + V V + +------------------------------------------------+ + | RSS communication protocol | + +------------------------------------------------+ + | ^ + | mhu_send_data() | mhu_receive_data() + | | + V | + +------------------------------------------------+ + | MHU driver | + +------------------------------------------------+ + | ^ + | Register access | IRQ + V | + +------------------------------------------------+ + | MHU HW on AP side | + +------------------------------------------------+ + ^ + | Physical wires + | + V + +------------------------------------------------+ + | MHU HW on RSS side | + +------------------------------------------------+ + | ^ + | IRQ | Register access + V | + +------------------------------------------------+ + | MHU driver | + +------------------------------------------------+ + | | + V V + +---------------+ +------------------------+ + | Measured boot | | Delegated attestation | + | service | | service | + +---------------+ +------------------------+ + + +RSS based Measured Boot +----------------------- + +Measured Boot is the process of cryptographically measuring (computing the hash +value of a binary) the code and critical data used at boot time. The +measurement must be stored in a tamper-resistant way, so the security state +of the device can be attested later to an external party. RSS provides a runtime +service which is meant to store measurements and associated metadata alongside. + +Data is stored in internal SRAM which is only accessible by the secure runtime +firmware of RSS. Data is stored in so-called measurement slots. A platform has +IMPDEF number of measurement slots. The measurement storage follows extend +semantics. This means that measurements are not stored directly (as it was +taken) instead they contribute to the current value of the measurement slot. +The extension implements this logic, where ``||`` stands for concatenation: + +.. code-block:: bash + + new_value_of_measurement_slot = Hash(old_value_of_measurement_slot || measurement) + +Supported hash algorithms: sha-256, sha-512 + +Measured Boot API +^^^^^^^^^^^^^^^^^ + +Defined here: + +- ``include/lib/psa/measured_boot.h`` + +.. code-block:: c + + psa_status_t + rss_measured_boot_extend_measurement(uint8_t index, + const uint8_t *signer_id, + size_t signer_id_size, + const uint8_t *version, + size_t version_size, + uint32_t measurement_algo, + const uint8_t *sw_type, + size_t sw_type_size, + const uint8_t *measurement_value, + size_t measurement_value_size, + bool lock_measurement); + +Measured Boot Metadata +^^^^^^^^^^^^^^^^^^^^^^ + +The following metadata can be stored alongside the measurement: + +- ``Signer-id``: Mandatory. The hash of the firmware image signing public key. +- ``Measurement algorithm``: Optional. The hash algorithm which was used to + compute the measurement (e.g.: sha-256, etc.). +- ``Version info``: Optional. The firmware version info (e.g.: 2.7). +- ``SW type``: Optional. Short text description (e.g.: BL1, BL2, BL31, etc.) + +.. Note:: + Version info is not implemented in TF-A yet. + + +The caller must specify in which measurement slot to extend a certain +measurement and metadata. A measurement slot can be extended by multiple +measurements. The default value is IMPDEF. All measurement slot is cleared at +reset, there is no other way to clear them. In the reference implementation, +the measurement slots are initialized to 0. At the first call to extend the +measurement in a slot, the extend operation uses the default value of the +measurement slot. All upcoming extend operation on the same slot contributes +to the previous value of that measurement slot. + +The following rules are kept when a slot is extended multiple times: + +- ``Signer-id`` must be the same as the previous call(s), otherwise a + PSA_ERROR_NOT_PERMITTED error code is returned. + +- ``Measurement algorithm``: must be the same as the previous call(s), + otherwise, a PSA_ERROR_NOT_PERMITTED error code is returned. + +In case of error no further action is taken (slot is not locked). If there is +a valid data in a sub-sequent call then measurement slot will be extended. The +rest of the metadata is handled as follows when a measurement slot is extended +multiple times: + +- ``SW type``: Cleared. +- ``Version info``: Cleared. + +.. Note:: + + Extending multiple measurements in the same slot leads to some metadata + information loss. Since RSS is not constrained on special HW resources to + store the measurements and metadata, therefore it is worth considering to + store all of them one by one in distinct slots. However, they are one-by-one + included in the platform attestation token. So, the number of distinct + firmware image measurements has an impact on the size of the attestation + token. + +The allocation of the measurement slot among RSS, Root and Realm worlds is +platform dependent. The platform must provide an allocation of the measurement +slot at build time. An example can be found in +``tf-a/plat/arm/board/tc/tc_bl1_measured_boot.c`` +Furthermore, the memory, which holds the metadata is also statically allocated +in RSS memory. Some of the fields have a static value (measurement algorithm), +and some of the values have a dynamic value (measurement value) which is updated +by the bootloaders when the firmware image is loaded and measured. The metadata +structure is defined in +``include/drivers/measured_boot/rss/rss_measured_boot.h``. + +.. code-block:: c + + struct rss_mboot_metadata { + unsigned int id; + uint8_t slot; + uint8_t signer_id[SIGNER_ID_MAX_SIZE]; + size_t signer_id_size; + uint8_t version[VERSION_MAX_SIZE]; + size_t version_size; + uint8_t sw_type[SW_TYPE_MAX_SIZE]; + size_t sw_type_size; + void *pk_oid; + bool lock_measurement; + }; + +Signer-ID API +^^^^^^^^^^^^^ + +This function calculates the hash of a public key (signer-ID) using the +``Measurement algorithm`` and stores it in the ``rss_mboot_metadata`` field +named ``signer_id``. +Prior to calling this function, the caller must ensure that the ``signer_id`` +field points to the zero-filled buffer. + +Defined here: + +- ``include/drivers/measured_boot/rss/rss_measured_boot.h`` + +.. code-block:: c + + int rss_mboot_set_signer_id(struct rss_mboot_metadata *metadata_ptr, + const void *pk_oid, + const void *pk_ptr, + size_t pk_len) + + +- First parameter is the pointer to the ``rss_mboot_metadata`` structure. +- Second parameter is the pointer to the key-OID of the public key. +- Third parameter is the pointer to the public key buffer. +- Fourth parameter is the size of public key buffer. +- This function returns 0 on success, a signed integer error code + otherwise. + +Build time config options +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``MEASURED_BOOT``: Enable measured boot. It depends on the platform + implementation whether RSS or TPM (or both) backend based measured boot is + enabled. +- ``MBOOT_RSS_HASH_ALG``: Determine the hash algorithm to measure the images. + The default value is sha-256. + +Measured boot flow +^^^^^^^^^^^^^^^^^^ + +.. figure:: ../resources/diagrams/rss_measured_boot_flow.svg + :align: center + +Sample console log +^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + INFO: Measured boot extend measurement: + INFO: - slot : 6 + INFO: - signer_id : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + INFO: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + INFO: - version : + INFO: - version_size: 0 + INFO: - sw_type : FW_CONFIG + INFO: - sw_type_size: 10 + INFO: - algorithm : 2000009 + INFO: - measurement : aa ea d3 a7 a8 e2 ab 7d 13 a6 cb 34 99 10 b9 a1 + INFO: : 1b 9f a0 52 c5 a8 b1 d7 76 f2 c1 c1 ef ca 1a df + INFO: - locking : true + INFO: FCONF: Config file with image ID:31 loaded at address = 0x4001010 + INFO: Loading image id=24 at address 0x4001300 + INFO: Image id=24 loaded: 0x4001300 - 0x400153a + INFO: Measured boot extend measurement: + INFO: - slot : 7 + INFO: - signer_id : b0 f3 82 09 12 97 d8 3a 37 7a 72 47 1b ec 32 73 + INFO: : e9 92 32 e2 49 59 f6 5e 8b 4a 4a 46 d8 22 9a da + INFO: - version : + INFO: - version_size: 0 + INFO: - sw_type : TB_FW_CONFIG + INFO: - sw_type_size: 13 + INFO: - algorithm : 2000009 + INFO: - measurement : 05 b9 dc 98 62 26 a7 1c 2d e5 bb af f0 90 52 28 + INFO: : f2 24 15 8a 3a 56 60 95 d6 51 3a 7a 1a 50 9b b7 + INFO: - locking : true + INFO: FCONF: Config file with image ID:24 loaded at address = 0x4001300 + INFO: BL1: Loading BL2 + INFO: Loading image id=1 at address 0x404d000 + INFO: Image id=1 loaded: 0x404d000 - 0x406412a + INFO: Measured boot extend measurement: + INFO: - slot : 8 + INFO: - signer_id : b0 f3 82 09 12 97 d8 3a 37 7a 72 47 1b ec 32 73 + INFO: : e9 92 32 e2 49 59 f6 5e 8b 4a 4a 46 d8 22 9a da + INFO: - version : + INFO: - version_size: 0 + INFO: - sw_type : BL_2 + INFO: - sw_type_size: 5 + INFO: - algorithm : 2000009 + INFO: - measurement : 53 a1 51 75 25 90 fb a1 d9 b8 c8 34 32 3a 01 16 + INFO: : c9 9e 74 91 7d 28 02 56 3f 5c 40 94 37 58 50 68 + INFO: - locking : true + +Delegated Attestation +--------------------- + +Delegated Attestation Service was mainly developed to support the attestation +flow on the ``ARM Confidential Compute Architecture`` (ARM CCA) [7]_. +The detailed description of the delegated attestation service can be found in +the ``Delegated Attestation Service Integration Guide`` [4]_ document. + +In the CCA use case, the Realm Management Monitor (RMM) relies on the delegated +attestation service of the RSS to get a realm attestation key and the CCA +platform token. BL31 does not use the service for its own purpose, only calls +it on behalf of RMM. The access to MHU interface and thereby to RSS is +restricted to BL31 only. Therefore, RMM does not have direct access, all calls +need to go through BL31. The RMM dispatcher module of the BL31 is responsible +for delivering the calls between the two parties. + +.. Note:: + Currently the connection between the RMM dispatcher and the PSA/RSS layer + is not yet implemented. RMM dispatcher just returns hard coded data. + +Delegated Attestation API +^^^^^^^^^^^^^^^^^^^^^^^^^ +Defined here: + +- ``include/lib/psa/delegated_attestation.h`` + +.. code-block:: c + + psa_status_t + rss_delegated_attest_get_delegated_key(uint8_t ecc_curve, + uint32_t key_bits, + uint8_t *key_buf, + size_t key_buf_size, + size_t *key_size, + uint32_t hash_algo); + + psa_status_t + rss_delegated_attest_get_token(const uint8_t *dak_pub_hash, + size_t dak_pub_hash_size, + uint8_t *token_buf, + size_t token_buf_size, + size_t *token_size); + +Attestation flow +^^^^^^^^^^^^^^^^ + +.. figure:: ../resources/diagrams/rss_attestation_flow.svg + :align: center + +Sample attestation token +^^^^^^^^^^^^^^^^^^^^^^^^ + +Binary format: + +.. code-block:: bash + + INFO: DELEGATED ATTEST TEST START + INFO: Get delegated attestation key start + INFO: Get delegated attest key succeeds, len: 48 + INFO: Delegated attest key: + INFO: 0d 2a 66 61 d4 89 17 e1 70 c6 73 56 df f4 11 fd + INFO: 7d 1f 3b 8a a3 30 3d 70 4c d9 06 c3 c7 ef 29 43 + INFO: 0f ee b5 e7 56 e0 71 74 1b c4 39 39 fd 85 f6 7b + INFO: Get platform token start + INFO: Get platform token succeeds, len: 1086 + INFO: Platform attestation token: + INFO: d2 84 44 a1 01 38 22 a0 59 03 d1 a9 0a 58 20 00 + INFO: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + INFO: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 + INFO: 01 00 58 21 01 cb 8c 79 f7 a0 0a 6c ce 12 66 f8 + INFO: 64 45 48 42 0e c5 10 bf 84 ee 22 18 b9 8f 11 04 + INFO: c7 22 31 9d fb 19 09 5c 58 20 aa aa aa aa aa aa + INFO: aa aa bb bb bb bb bb bb bb bb cc cc cc cc cc cc + INFO: cc cc dd dd dd dd dd dd dd dd 19 09 5b 19 30 00 + INFO: 19 09 5f 89 a4 05 58 20 bf e6 d8 6f 88 26 f4 ff + INFO: 97 fb 96 c4 e6 fb c4 99 3e 46 19 fc 56 5d a2 6a + INFO: df 34 c3 29 48 9a dc 38 04 67 31 2e 36 2e 30 2b + INFO: 30 01 64 52 54 5f 30 02 58 20 90 27 f2 46 ab 31 + INFO: 85 36 46 c4 d7 c6 60 ed 31 0d 3c f0 14 de f0 6c + INFO: 24 0b de b6 7a 84 fc 3f 5b b7 a4 05 58 20 b3 60 + INFO: ca f5 c9 8c 6b 94 2a 48 82 fa 9d 48 23 ef b1 66 + INFO: a9 ef 6a 6e 4a a3 7c 19 19 ed 1f cc c0 49 04 67 + INFO: 30 2e 30 2e 30 2b 30 01 64 52 54 5f 31 02 58 20 + INFO: 52 13 15 d4 9d b2 cf 54 e4 99 37 44 40 68 f0 70 + INFO: 7d 73 64 ae f7 08 14 b0 f7 82 ad c6 17 db a3 91 + INFO: a4 05 58 20 bf e6 d8 6f 88 26 f4 ff 97 fb 96 c4 + INFO: e6 fb c4 99 3e 46 19 fc 56 5d a2 6a df 34 c3 29 + INFO: 48 9a dc 38 04 67 31 2e 35 2e 30 2b 30 01 64 52 + INFO: 54 5f 32 02 58 20 8e 5d 64 7e 6f 6c c6 6f d4 4f + INFO: 54 b6 06 e5 47 9a cc 1b f3 7f ce 87 38 49 c5 92 + INFO: d8 2f 85 2e 85 42 a4 05 58 20 bf e6 d8 6f 88 26 + INFO: f4 ff 97 fb 96 c4 e6 fb c4 99 3e 46 19 fc 56 5d + INFO: a2 6a df 34 c3 29 48 9a dc 38 04 67 31 2e 35 2e + INFO: 30 2b 30 01 60 02 58 20 b8 01 65 a7 78 8b c6 59 + INFO: 42 8d 33 10 85 d1 49 0a dc 9e c3 ee df 85 1b d2 + INFO: f0 73 73 6a 0c 07 11 b8 a4 05 58 20 b0 f3 82 09 + INFO: 12 97 d8 3a 37 7a 72 47 1b ec 32 73 e9 92 32 e2 + INFO: 49 59 f6 5e 8b 4a 4a 46 d8 22 9a da 04 60 01 6a + INFO: 46 57 5f 43 4f 4e 46 49 47 00 02 58 20 21 9e a0 + INFO: 13 82 e6 d7 97 5a 11 13 a3 5f 45 39 68 b1 d9 a3 + INFO: ea 6a ab 84 23 3b 8c 06 16 98 20 ba b9 a4 05 58 + INFO: 20 b0 f3 82 09 12 97 d8 3a 37 7a 72 47 1b ec 32 + INFO: 73 e9 92 32 e2 49 59 f6 5e 8b 4a 4a 46 d8 22 9a + INFO: da 04 60 01 6d 54 42 5f 46 57 5f 43 4f 4e 46 49 + INFO: 47 00 02 58 20 41 39 f6 c2 10 84 53 c5 17 ae 9a + INFO: e5 be c1 20 7b cc 24 24 f3 9d 20 a8 fb c7 b3 10 + INFO: e3 ee af 1b 05 a4 05 58 20 b0 f3 82 09 12 97 d8 + INFO: 3a 37 7a 72 47 1b ec 32 73 e9 92 32 e2 49 59 f6 + INFO: 5e 8b 4a 4a 46 d8 22 9a da 04 60 01 65 42 4c 5f + INFO: 32 00 02 58 20 5c 96 20 e1 e3 3b 0f 2c eb c1 8e + INFO: 1a 02 a6 65 86 dd 34 97 a7 4c 98 13 bf 74 14 45 + INFO: 2d 30 28 05 c3 a4 05 58 20 b0 f3 82 09 12 97 d8 + INFO: 3a 37 7a 72 47 1b ec 32 73 e9 92 32 e2 49 59 f6 + INFO: 5e 8b 4a 4a 46 d8 22 9a da 04 60 01 6e 53 45 43 + INFO: 55 52 45 5f 52 54 5f 45 4c 33 00 02 58 20 f6 fb + INFO: 62 99 a5 0c df db 02 0b 72 5b 1c 0b 63 6e 94 ee + INFO: 66 50 56 3a 29 9c cb 38 f0 ec 59 99 d4 2e a4 05 + INFO: 58 20 b0 f3 82 09 12 97 d8 3a 37 7a 72 47 1b ec + INFO: 32 73 e9 92 32 e2 49 59 f6 5e 8b 4a 4a 46 d8 22 + INFO: 9a da 04 60 01 6a 48 57 5f 43 4f 4e 46 49 47 00 + INFO: 02 58 20 98 5d 87 21 84 06 33 9d c3 1f 91 f5 68 + INFO: 8d a0 5a f0 d7 7e 20 51 ce 3b f2 a5 c3 05 2e 3c + INFO: 8b 52 31 19 01 09 78 1c 68 74 74 70 3a 2f 2f 61 + INFO: 72 6d 2e 63 6f 6d 2f 43 43 41 2d 53 53 44 2f 31 + INFO: 2e 30 2e 30 19 09 62 71 6e 6f 74 2d 68 61 73 68 + INFO: 2d 65 78 74 65 6e 64 65 64 19 09 61 44 ef be ad + INFO: de 19 09 60 77 77 77 77 2e 74 72 75 73 74 65 64 + INFO: 66 69 72 6d 77 61 72 65 2e 6f 72 67 58 60 29 4e + INFO: 4a d3 98 1e 3b 70 9f b6 66 ed 47 33 0e 99 f0 b1 + INFO: c3 f2 bc b2 1d b0 ae 90 0c c4 82 ff a2 6f ae 45 + INFO: f6 87 09 4a 09 21 77 ec 36 1c 53 b8 a7 9b 8e f7 + INFO: 27 eb 7a 09 da 6f fb bf cb fd b3 e5 e9 36 91 b1 + INFO: 92 13 c1 30 16 b4 5c 49 5e c0 c1 b9 01 5c 88 2c + INFO: f8 2f 3e a4 a2 6d e4 9d 31 6a 06 f7 a7 73 + INFO: DELEGATED ATTEST TEST END + +JSON format: + +.. code-block:: JSON + + { + "CCA_PLATFORM_CHALLENGE": "b'0000000000000000000000000000000000000000000000000000000000000000'", + "CCA_PLATFORM_INSTANCE_ID": "b'01CB8C79F7A00A6CCE1266F8644548420EC510BF84EE2218B98F1104C722319DFB'", + "CCA_PLATFORM_IMPLEMENTATION_ID": "b'AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDD'", + "CCA_PLATFORM_LIFECYCLE": "secured_3000", + "CCA_PLATFORM_SW_COMPONENTS": [ + { + "SIGNER_ID": "b'BFE6D86F8826F4FF97FB96C4E6FBC4993E4619FC565DA26ADF34C329489ADC38'", + "SW_COMPONENT_VERSION": "1.6.0+0", + "SW_COMPONENT_TYPE": "RT_0", + "MEASUREMENT_VALUE": "b'9027F246AB31853646C4D7C660ED310D3CF014DEF06C240BDEB67A84FC3F5BB7'" + }, + { + "SIGNER_ID": "b'B360CAF5C98C6B942A4882FA9D4823EFB166A9EF6A6E4AA37C1919ED1FCCC049'", + "SW_COMPONENT_VERSION": "0.0.0+0", + "SW_COMPONENT_TYPE": "RT_1", + "MEASUREMENT_VALUE": "b'521315D49DB2CF54E49937444068F0707D7364AEF70814B0F782ADC617DBA391'" + }, + { + "SIGNER_ID": "b'BFE6D86F8826F4FF97FB96C4E6FBC4993E4619FC565DA26ADF34C329489ADC38'", + "SW_COMPONENT_VERSION": "1.5.0+0", + "SW_COMPONENT_TYPE": "RT_2", + "MEASUREMENT_VALUE": "b'8E5D647E6F6CC66FD44F54B606E5479ACC1BF37FCE873849C592D82F852E8542'" + }, + { + "SIGNER_ID": "b'BFE6D86F8826F4FF97FB96C4E6FBC4993E4619FC565DA26ADF34C329489ADC38'", + "SW_COMPONENT_VERSION": "1.5.0+0", + "SW_COMPONENT_TYPE": "", + "MEASUREMENT_VALUE": "b'B80165A7788BC659428D331085D1490ADC9EC3EEDF851BD2F073736A0C0711B8'" + }, + { + "SIGNER_ID": "b'b0f382091297d83a377a72471bec3273e99232e24959f65e8b4a4a46d8229ada'", + "SW_COMPONENT_VERSION": "", + "SW_COMPONENT_TYPE": "FW_CONFIG\u0000", + "MEASUREMENT_VALUE": "b'219EA01382E6D7975A1113A35F453968B1D9A3EA6AAB84233B8C06169820BAB9'" + }, + { + "SIGNER_ID": "b'b0f382091297d83a377a72471bec3273e99232e24959f65e8b4a4a46d8229ada'", + "SW_COMPONENT_VERSION": "", + "SW_COMPONENT_TYPE": "TB_FW_CONFIG\u0000", + "MEASUREMENT_VALUE": "b'4139F6C2108453C517AE9AE5BEC1207BCC2424F39D20A8FBC7B310E3EEAF1B05'" + }, + { + "SIGNER_ID": "b'b0f382091297d83a377a72471bec3273e99232e24959f65e8b4a4a46d8229ada'", + "SW_COMPONENT_VERSION": "", + "SW_COMPONENT_TYPE": "BL_2\u0000", + "MEASUREMENT_VALUE": "b'5C9620E1E33B0F2CEBC18E1A02A66586DD3497A74C9813BF7414452D302805C3'" + }, + { + "SIGNER_ID": "b'b0f382091297d83a377a72471bec3273e99232e24959f65e8b4a4a46d8229ada'", + "SW_COMPONENT_VERSION": "", + "SW_COMPONENT_TYPE": "SECURE_RT_EL3\u0000", + "MEASUREMENT_VALUE": "b'F6FB6299A50CDFDB020B725B1C0B636E94EE6650563A299CCB38F0EC5999D42E'" + }, + { + "SIGNER_ID": "b'b0f382091297d83a377a72471bec3273e99232e24959f65e8b4a4a46d8229ada'", + "SW_COMPONENT_VERSION": "", + "SW_COMPONENT_TYPE": "HW_CONFIG\u0000", + "MEASUREMENT_VALUE": "b'985D87218406339DC31F91F5688DA05AF0D77E2051CE3BF2A5C3052E3C8B5231'" + } + ], + "CCA_ATTESTATION_PROFILE": "http://arm.com/CCA-SSD/1.0.0", + "CCA_PLATFORM_HASH_ALGO_ID": "not-hash-extended", + "CCA_PLATFORM_CONFIG": "b'EFBEADDE'", + "CCA_PLATFORM_VERIFICATION_SERVICE": "www.trustedfirmware.org" + } + +RSS OTP Assets Management +------------------------- + +RSS provides access for AP to assets in OTP, which include keys for image +signature verification and non-volatile counters for anti-rollback protection. + +Non-Volatile Counter API +^^^^^^^^^^^^^^^^^^^^^^^^ + +AP/RSS interface for retrieving and incrementing non-volatile counters API is +as follows. + +Defined here: + +- ``include/lib/psa/rss_platform_api.h`` + +.. code-block:: c + + psa_status_t rss_platform_nv_counter_increment(uint32_t counter_id) + + psa_status_t rss_platform_nv_counter_read(uint32_t counter_id, + uint32_t size, uint8_t *val) + +Through this service, we can read/increment any of the 3 non-volatile +counters used on an Arm CCA platform: + +- ``Non-volatile counter for CCA firmware (BL2, BL31, RMM).`` +- ``Non-volatile counter for secure firmware.`` +- ``Non-volatile counter for non-secure firmware.`` + +Public Key API +^^^^^^^^^^^^^^ + +AP/RSS interface for reading the ROTPK is as follows. + +Defined here: + +- ``include/lib/psa/rss_platform_api.h`` + +.. code-block:: c + + psa_status_t rss_platform_key_read(enum rss_key_id_builtin_t key, + uint8_t *data, size_t data_size, size_t *data_length) + +Through this service, we can read any of the 3 ROTPKs used on an +Arm CCA platform: + +- ``ROTPK for CCA firmware (BL2, BL31, RMM).`` +- ``ROTPK for secure firmware.`` +- ``ROTPK for non-secure firmware.`` + +References +---------- + +.. [1] https://tf-m-user-guide.trustedfirmware.org/platform/arm/rss/readme.html +.. [2] https://tf-m-user-guide.trustedfirmware.org/platform/arm/rss/rss_comms.html +.. [3] https://git.trustedfirmware.org/TF-M/tf-m-extras.git/tree/partitions/measured_boot/measured_boot_integration_guide.rst +.. [4] https://git.trustedfirmware.org/TF-M/tf-m-extras.git/tree/partitions/delegated_attestation/delegated_attest_integration_guide.rst +.. [5] https://tf-m-user-guide.trustedfirmware.org/platform/arm/rss/rss_key_management.html +.. [6] https://developer.arm.com/-/media/Files/pdf/PlatformSecurityArchitecture/Architect/DEN0063-PSA_Firmware_Framework-1.0.0-2.pdf?revision=2d1429fa-4b5b-461a-a60e-4ef3d8f7f4b4&hash=3BFD6F3E687F324672F18E5BE9F08EDC48087C93 +.. [7] https://developer.arm.com/documentation/DEN0096/A_a/?lang=en + +-------------- + +*Copyright (c) 2023, Arm Limited. All rights reserved.* |