Skip to content

Commit

Permalink
Rewritten the explanations of how the UDI and UDS are actually
Browse files Browse the repository at this point in the history
stored in the FPGA, and how they are accessed

Signed-off-by: Joachim Strömbergson <[email protected]>
  • Loading branch information
secworks committed Apr 3, 2024
1 parent ad12606 commit 33fe3ed
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 32 deletions.
27 changes: 11 additions & 16 deletions hw/application_fpga/core/tk1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,22 +110,17 @@ secret for any secrets it needs to perform its intended use case.
ADDR_UDI_LAST: 0x31
```

These registers provide read access to the 64-bit unique device
identity. The registers can't be written to.

The 2 UDI words are stored using 32 named LUT4s identified by
"udi\_rom\_idx".

We use bit indexing from all of the 32 LUTs to store each bit of the
word, i.e., the first UDI word consists of bit 0 from each 32 LUTs,
the second word consists of bit 1 from each of the 32 LUTs, and so
on... for a maximum storage of 16 words, but we use only 2.

The UDI does not occupy the entire LUT4 instance and to preserve
hardware resources and not having to care about all the address bits
the UDI should be repeated over the unused portion of the LUT4
instance. This eliminates the need to drive the three MSB pins into
the LUT4 while still achieving the correct output.
These read-only registers provide access to the 64-bit Unique Device
Identity (UDI).

The two UDI words are stored using 32 named SB_LUT4 FPGA multiplexer
(MUX) instances, identified in the source code as "udi\_rom\_idx". One
instance for each bit in core read_data output bus.

Each SB_LUT4 MUX is able to store 16 bits of data, in total 512
bits. But since the UDI is 64 bits, we only use the two LSBs in each
MUX.


### RAM memory protecion

Expand Down
40 changes: 24 additions & 16 deletions hw/application_fpga/core/uds/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ Unique Device Secret core
## Introduction

This core store and protect the Unique Device Secret (UDS) asset. The
UDS can be accessed as eight separate 32-bit words. The words can be
accessed in any order, but a given word can only be accessed once
between reset cycles. The words can only be accessed as long as the
fw_app_mode input is low, implying that the CPU is executing the FW.
UDS can be accessed as eight separate 32-bit words. The words can only
be accessed as long as the fw_app_mode input is low, implying that the
CPU is executing the FW.

Each UDS words has a companion read bit that is set when the word is
accessed. This means that the even if the chip select (cs) control
The UDS words can be accessed in any order, but a given word can only
be accessed once between reset cycles. This read once functionality is
implemented with a companion read bit for each word. The read bit is
set when the word is first accessed. The read bit controls if the real
UDS word is returned or not.

This means that the even if the chip select (cs) control
input is forced high, the content will become all zero when the read
bit has been set after one cycle.


## API
There are eight addresses in the API. These are defined by the
two values ADDR_UDS_FIRST and ADDR_UDS_LAST:
Expand All @@ -31,15 +36,18 @@ Any access to another address will be ignored by the core.

## Implementation

The 8 UDS words are stored using 32 named LUT4s identified by
"uds\_rom\_idx".
These read-only registers provide read access to the 256-bit UDS.

The eight UDS words are stored using 32 named SB_LUT4 FPGA multiplexer
(MUX) instances, identified in the source code as "uds\_rom\_idx". One
instance for each bit in the core read_data output bus.

We use bit indexing from all of the 32 LUTs to store each bit of the
word, i.e., the first UDS word consists of bit 0 from each 32 LUTs,
the second word consists of bit 1 from each of the 32 LUTs, and so
on... for a maximum storage of 16 words.
Each SB_LUT4 MUX is able to store 16 bits of data, in total 512
bits. But since the UDS is 256 bits, we only use the eight LSBs in
each MUX.

The most significant bit in the LUT address serves as the read-enable
input. This requires the lower half of initialization bits to be
forced to zero, ensuring that the memory outputs zero when the
read-enable signal is inactive.
The eighth MSBs in each MUX will be initialized to zero. The read
access bit (se description above) for a given word is used as the
highest address bit to the MUXes. This forces any subsequent accesses
to a UDS word to read from the MUX MSBs, not the LSBs where the UDS is
stored.

0 comments on commit 33fe3ed

Please sign in to comment.