= Table of Contents =
- Reference
- Terms and abbreviations
- Scope
- Introduction
- Rollback attack in secure storage data
- Trusted non-volatile (NV) counters
- TF-M NV Counters
- SST Rollback Protection Design
= Reference =
| Ref | Title | Doc No
|-----|-------|-------
| [1] | [[https://pages.arm.com/psa-resources-tbsa-m.html | Arm® Platform Security Architecture Trusted Base System Architecture for Arm®v6-M, Arm®v7-M and Arm®v8-M 1.0]] | DEN 0083
| [2] | [[https://git.trustedfirmware.org/trusted-firmware-m.git/tree/platform/include/tfm_plat_nv_counters.h | TF-M NV Counter Platform Interface Header]] | SHA: 65f816ecad12900fe75d5856af9a569622ed66c7
= Terms and abbreviations =
| Term | Meaning
|--------|---------------------------------------
| MAC | Message Authentication Code
| MTP | Multiple time Programmable
| NV | Non-Volatile
| NVC | Non-Volatile Counter
| OTP | One-time Programmable
| SoC | System on Chip
| SST | Secure Storage
| TBSA-M | Trusted Base System Architecture
| TF-M | Trusted Firmware for M-class devices
= Scope =
The scope of this document is to provide a design proposal to add a rollback protection mechanism in the secure storage service in the context of Trusted Firmware for M-class devices (TF-M).
= Introduction =
== Rollback attack in secure storage data ==
In the context of secure storage, a rollback attack is when a malicious actor replaces the current secure storage data with an older valid version of it and that implies a security break of the system. This attack can bring back old keys/credentials which were replaced, invalidated or removed in/from the system; and/or it can remove keys/credentials generated and stored in the SST area. Due to this security break, the system can lose access to certain local or remote resources (i.e. server access, etc.), encrypt new data using a key which was compromised, etc.
For example, this attack can take place when the secure storage data is stored in an external memory (off-chip flash memory, SD card, etc). That external memory can be physically accessed which allows the attacker to read and write in that device.
== Trusted non-volatile (NV) counters ==
The Trusted Base System Architecture (TBSA-M) defines non-volatile (NV) counters or version counters as a counter with the following properties [1]:
- It must only be possible to increment a version counter through a Trusted
access.
- It must only be possible to increment a version counter. It must not be
possible to decrement it.
- When a version counter reaches its maximum value, it must not roll over, and
no further changes must be possible.
- A version counter must be non-volatile, and the stored value must survive a
power down period up to the lifetime of the device.
A compliant TBSA-M [1] system must implement a core set of Trusted non-volatile counters, which are required for version control of firmware and Trusted data held in external storage. In order to prevent replay attacks, it is important that these counters cannot be rolled back.
Ideally, a SoC implements NV counters using on-chip multiple time programmable (MTP) storage, for example embedded flash technology. One-time programmable (OTP) storage, based on anti-fuse technology, is widely available and cost effective. A non-volatile counter, based on OTP, can be implemented by mapping each possible value that is greater than one onto a separate fuse bit. Each counter increment is achieved by programming a further bit. Because one bit is required for each value, this approach has the downside of being very costly for large counters, for example a 10-bit counter requires 1024 bits of storage. For this reason, practical limitations must be imposed on the maximum count values for fuse-based implementations.
A suitable implementation might employ one counter per software instance, or group together a list of version numbers inside a database file, which is itself versioned using a single counter.
== TF-M NV Counters ==
The secure storage service, and other components in TF-M, uses the NV counters to prevent rollback and/or replay attacks. To have a platform independent API to access the NV counters, TF-M defines a platform NV counters interfaces as follows [2]:
| TF-M NV Counters in tfm_nv_counter_t
|------------------------------------------
|TFM_SST_NV_COUNTER_1
|TFM_SST_NV_COUNTER_2
|TFM_SST_NV_COUNTER_3
=== tfm_plat_init_nv_counter() ===
Initializes all non-volatile (NV) counters.
```
enum tfm_plat_err_t tfm_plat_init_nv_counter(void);
```
**Parameters**
| Direction | Type | Name | Description
|-----------|------|------|--------------
| | void | | None
**Return**
A status indicating the success/failure of the operation as specified in tfm_plat_err_t.
| Type | Description
|------|--------------
| TFM_PLAT_ERR_SUCCESS | The operation completed successfully.
| TFM_PLAT_ERR_SYSTEM_ERR | The operation has failed as there was a system error (flash error, etc).
=== tfm_plat_read_nv_counter() ===
Reads the given non-volatile (NV) counter.
```
enum tfm_plat_err_t tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,
uint32_t size, uint8_t *val);
```
**Parameters**
| Direction | Type | Name | Description
|-----------|------|------|--------------
| in | enum tfm_nv_counter_t | counter_id | NV counter ID to read
| in | uint32_t | size | Size of the buffer to store NV counter value in bytes.
| out | uint8_t * | val | Pointer to store the current NV counter value.
**Return**
A status indicating the success/failure of the operation as specified in tfm_plat_err_t.
| Type | Description
|------|--------------
| TFM_PLAT_ERR_SUCCESS | The operation completed successfully.
| TFM_PLAT_ERR_SYSTEM_ERR | The operation has failed as there was a system error (flash error, etc).
=== tfm_plat_increment_nv_counter() ===
Increments the given non-volatile (NV) counter.
```
enum tfm_plat_err_t tfm_plat_increment_nv_counter(enum tfm_nv_counter_t counter_id);
```
**Parameters**
| Direction | Type | Name | Description
|-----------|------|------|--------------
| in | enum tfm_nv_counter_t | counter_id | NV counter ID to increase
**Return**
A status indicating the success/failure of the operation as specified in tfm_plat_err_t.
| Type | Description
|------|--------------
| TFM_PLAT_ERR_SUCCESS | The operation completed successfully.
| TFM_PLAT_ERR_MAX_VALUE | The NV counter cannot be incremented as it has reached its maximum value.
| TFM_PLAT_ERR_SYSTEM_ERR | The operation has failed as there was a system error (flash error, etc).
The system integrators **may** implement this interfaces based on the target capabilities and set the **SST_ROLLBACK_PROTECTION** flag to compile in the rollback protection code.
= SST Rollback Protection Design =
In SST service, the object table is the component in the object system which keeps track of the objects stored in the SST area. This table stores the authentication tag of each object stored in the SST area. An entry is created in the table when the object is created or updated in the SST area. An entry is removed when the object is updated or deleted from the SST area.
When the SST service boots, the object table is read from flash and its content authenticated to be sure the object table content has not been manipulated. Each time there is a change in the SST area, the object table is updated, a new authentication tag is generated and stored in the object table header. Then, the object header and new content is written in the flash. The SST rollback protection design uses a NV counter value as associated data to authenticate the object table content. So, if an attacker replaces the object table content by an older version, the authentication will fail and the SST service will report it. Each time there is a create, write or delete operation, as the SST area content and object table changes, the NV counter value will be incremented and used to generate a new authentication tag.
The proposed design uses three NV counters to protect the whole secure storage area. The reason of using 3 NV counters instead of 1 is to prevent rollback attacks and support a recovery mechanism when there is a power cut, with or without flash manipulation, in the middle of a create, write or delete operation at the moment where the new object table is written in flash and the NV counters are not yet incremented. The goal at the end of each operation, it is to have the NV counters with the same value. Hence, only one NV counter value.
In the rollback protection design, every time there is an operation which generates a change in the SST area, that is reflected in the object table and the SST service saves the new object table as described in the figure 1.
The object table save operation increments and reads the SST NV counter 1 (TFM_SST_NV_COUNTER_1), uses that incremented value as associated data in order to generate the authentication tag and stores it in the object table header. Then, the new object table header and content is stored in flash and the other 2 NV counters (TFM_SST_NV_COUNTER_2 and TFM_SST_NV_COUNTER_3) are incremented to have them aligned with NV counter 1. So, at the end of the save operation the NV counters will have the same value.
{F22891, size=full}
//Figure 1: Object table save flow diagram//
When the SST service starts, it uses the NV counter 1 value to verify the object table content after read it from flash. If the verification success, the the SST service continues with the start process. Otherwise, it returns an initialization error. In case, the NV counters do not have the same values, the SST service initialization process will validate the object table against the NV counters values as described in the table below.
| SST version | NVC1 | NVC2 | NVC3 | Result
|-------------|------|------|------|----------
| X | X | X | X | Valid
| N | X | X | X | Invalid
| X | X | X | N | Valid
| N | X | X | N | Invalid
| N | X | N | N | Valid
| X | X | N | N | Valid
| X | X | M | N | Valid
| M | X | M | N | Invalid
| N | X | M | N | Invalid
//Where X, N and M are different counter values.//
If the object table authentication success with the NVC_1 value, the object table is valid. In case, the authentication fails with NVC_1 value but it success with NVC_3 value, when NVC_2 and NVC_3 values are equals, the object table is valid. In all the other cases, the object table is rejected even if the authentication success with NVC_3 value. If NVC3 is different from NVC2, it is possible to load an old object table in the system by manipulating the file system to return a system error when the table is being written into the file system layer and triggering power fault before increasing the NVC3. So, in that case, NVC3 value cannot be used to validate an old object table at the init process.
The figure 2 shows the SST service initialization flow described before, and extended in case there are 2 object tables in the SST flash area.
{F22893, size=full}
//Figure 2: Object table validation flow diagram//