| RSE provisioning |
| ================ |
| |
| Provisioning theory |
| ------------------- |
| |
| The LifeCycle Manager (LCM) controls access to the RSE OTP, and includes a |
| state-machine that controls Lifecycle-state (LCS) transitions. The LCM is |
| derived from the OTP management and state machine subsystems of the |
| CryptoCell-3XX series accelerators, and will be familiar to those who have |
| worked with them. |
| |
| When the chip hasn't been provisioned, the OTP is blank, which means the LCM is |
| in "Virgin" Test/Production mode "TP mode" state. The first step for |
| provisioning must be to set the LCM to either test-chip mode "TCI" or |
| production-chip mode "PCI". In TCI mode the RTL key is masked to avoid |
| disclosure, several OTP fields are changed from write-only to read-write, to aid |
| in debugging, and debugging is not limited in secure provisioning mode (though |
| the RTL key reads as zero). If ``TFM_DUMMY_PROVISIONING`` is enabled in cmake |
| (which it is by default) then the chip will be set to TCI mode. If this option |
| is not enabled, execution will pause to allow the setting to be set by a |
| debugger. |
| |
| Once the TP mode has been set, the chip is then is Chip Manufacturer |
| provisioning state "CM". This mode is intended for the provisioning of the HUK, |
| GUK, CM provisioning key, CM code-encryption key, the root-of-trust public key |
| and the CM config. To provision these fields, The firmware must first receive a |
| provisioning bundle via a debugger. This bundle must be placed at the start of |
| VM0 + an offset the size of the OTP DMA ICS (usually 0x400). This bundle |
| contains the keys and also code to perform the provisioning such as a driver for |
| the LCM, and a function to randomly generate the HUK via the CryptoCell TRNG. |
| The chip must then enter secure provisioning mode by setting the SP_ENABLE |
| register. This causes a reset (but does not clear the RSE SRAMs), and allows |
| access to the RTL key by exporting it to the KMU, though in secure provisioning |
| mode the ability to debug the RSE is disabled, to prevent disclosure of the |
| decrypted provisioning bundle values. The RSE will then decrypt and authenticate |
| the bundle using the RTL key. Under TCI mode the RTL key is zeroed, the bundle |
| generation tool must use a zeroed key to encrypt and sign the bundle. Once the |
| CM provisioning bundle has been unpacked, the RSE will execute the code which |
| will provision the CM provisioning data into OTP. The RSE must be cold-reset, |
| which will disable secure provisioning mode. If ``TFM_DUMMY_PROVISIONING`` is |
| enabled the reset will happen automatically, else the external provisioning |
| device should read the provisioning state from the GPIO/PSI (which is set via |
| the ``rse_sysctrl`` register) and perform the reset. |
| |
| After the cold reset, the RSE will automatically transition to Device |
| Manufacturer provisioning state "DM" as the LCM hardware state-machine reads the |
| values of the cm_config_1 and cm_config_2 fields as non-zero. This state is |
| designed to provision the DM provisioning key, the DM code-encryption key and |
| the DM config. The procedure follows the same steps as the CM provisioning flow, |
| with the exception that the bundle will now be encrypted and signed using the CM |
| provisioning key and must be placed at the base of VM1. As before, once the |
| provisioning bundle has been unpacked/run, the RSE must either be cold-reset or |
| will perform this automatically. |
| |
| After the cold reset, the device will now be in Secure Enable "SE" mode, due to |
| the dm_config_1 field being non-zero. Debug may be limited based on the hardware |
| DCU mask for SE state. Provisioning will not be run on boot. |
| |
| Practical RSE provisioning |
| -------------------------- |
| |
| The RSE buildsystem produces two provisioning bundles (containing both code and |
| data), and then encrypts and signs them with the RTL key to produce |
| ``encrypted_cm_provisioning_bundle.bin`` and |
| ``encrypted_dm_provisioning_bundle.bin``. |
| |
| .. Note:: |
| Currently encrypted provisioning bundles are not supported due to a lack of |
| AEAD encryption support in the cc312-rom-lib driver. The |
| encrypted_*_provisioning_bundle.bin files should still be used, but note that |
| their contents are not encrypted. |
| |
| On first boot, the RSE is in Virgin state. If the RSE firmware was built with |
| ``TFM_DUMMY_PROVISIONING`` enabled then it will automatically set the chip to |
| TCI mode and cold-reset. Production ROM implementations must disable |
| ``TFM_DUMMY_PROVISIONING``, which will cause RSE to loop in the ROM until either |
| TCI or PCI mode is set with a debugger. It is possible to set the TP mode in the |
| LCS registers directly, however it may be easier to set the ``tp_mode`` variable |
| in the frame where RSE is looping, at which point the loop will exit and the TP |
| mode will be set by the ROM code. |
| |
| On non-virgin boot in CM lifecycle state, RSE checks the start of VM0 for the |
| magic constant ``0xC0DEFEED``, which is required to be the first word in the CM |
| provisioning bundle. There is also a second check for a constant at the end of |
| the bundle to ensure the bundle has finished writing. The RSE will perform this |
| check in a loop until a bundle is found. |
| |
| This procedure is repeated for DM LCS, except that the magic constant is |
| ``0xBEEFFEED`` and the bundle must be loaded to the base of VM1. Note that the |
| size of RSE memory may vary depending on implementation, so the load address of |
| the DM bundle may change. |
| |
| In production systems it is intended that these bundles are loaded by a |
| debugger, but for development systems it may be too onerous to perform this |
| procedure, particularly if the system is one that has ephemeral OTP such as an |
| FVP. The preferred solution is to preload to the provisioning bundles into VM0 |
| and VM1 as part of the image loading, which is supported on FVPs but may not be |
| on other systems. An alternative solution is to perform provisioning manually |
| once, and then to save the state of the OTP in SE LCS and then preload that on |
| subsequent boots. |
| |
| RSE provisioning GPIO signalling |
| -------------------------------- |
| The state of the RSE ROM boot/provisioning flow is signalled outside of the RSE |
| subsystem via the GPIOs as part of the Persistent State Interface (PSI). The PSI |
| signals the lifecycle state as a hardware signal, but additionally the software |
| can signal over the PSI by setting the ``rse_sysctrl`` register. |
| |
| The boot state is encoded in the lowest 4 bits of the ``rse_sysctrl`` register, |
| and has meaning as follows: |
| |
| +--------+------------------------------------------------------------------+ |
| | Signal | State | |
| +========+==================================================================+ |
| | 0x0 | RSE cold boot default | |
| +--------+------------------------------------------------------------------+ |
| | 0x1 | Virgin chip idle, ready to set PCI/TCI mode | |
| +--------+------------------------------------------------------------------+ |
| | 0x2 | CM LCS idle, waiting for CM provisioning bundle | |
| +--------+------------------------------------------------------------------+ |
| | 0x3 | RMA LCS idle | |
| +--------+------------------------------------------------------------------+ |
| | 0x4 | CM secure provisioning started, secure provisioning mode enabled | |
| +--------+------------------------------------------------------------------+ |
| | 0x5 | CM secure provisioning failed due to bundle authentication error | |
| +--------+------------------------------------------------------------------+ |
| | 0x6 | CM secure provisioning failed due to other error | |
| +--------+------------------------------------------------------------------+ |
| | 0x7 | CM secure provisioning succeeded | |
| +--------+------------------------------------------------------------------+ |
| | 0x8 | DM LCS idle, waiting for CM provisioning bundle | |
| +--------+------------------------------------------------------------------+ |
| | 0x9 | DM secure provisioning started, secure provisioning mode enabled | |
| +--------+------------------------------------------------------------------+ |
| | 0xa | DM secure provisioning failed due to bundle authentication error | |
| +--------+------------------------------------------------------------------+ |
| | 0xb | DM secure provisioning failed due to other error | |
| +--------+------------------------------------------------------------------+ |
| | 0xc | DM secure provisioning succeeded | |
| +--------+------------------------------------------------------------------+ |
| | 0xd | SE LCS standard boot | |
| +--------+------------------------------------------------------------------+ |
| |
| -------------- |
| |
| *Copyright (c) 2022-2024, Arm Limited. All rights reserved.* |