tillitis-key/hw/application_fpga
Michael Cardell Widerkrantz 86aedcce69
Revise top-level README for the hardware design
Merged information from fpga.md, and hence fpga.md is removed.
2024-11-20 15:48:49 +01:00
..
core doc: Harmonize preformatted in tk1 core 2024-11-15 15:01:31 +01:00
data A construction of a minimal SPI master. 2024-06-11 15:28:29 +02:00
fw Harmonize the naming of firmware and app mode. 2024-11-12 15:13:59 +01:00
rtl Change "rosc" references to "trng" 2024-11-14 16:35:51 +01:00
tb Rename top level simulation files 2024-11-12 15:33:33 +01:00
tools Add place and route script 2024-10-22 15:20:39 +02:00
application_fpga.bin.sha256 Updated application_fpga.bin.sha256 with new hash 2024-11-14 16:35:51 +01:00
config.vlt Config verilator lint to ignore known 3rd-party warnings; let warnings be fatal 2023-03-01 13:37:31 +01:00
firmware.bin.sha512 FPGA: Move RAM address and data scrambling into the RAM module. 2024-08-30 10:53:13 +02:00
Makefile Add clangd target 2024-11-15 15:01:31 +01:00
README.md Revise top-level README for the hardware design 2024-11-20 15:48:49 +01:00

TKey hardware design

The Application FPGA block diagram

The application FPGA is implemented using a Lattice iCE40 UltraPlus UP5K device. Only open tools are used in the toolchain.

The design top level is in rtl/application_fpga.v. It contains instances of all cores as well as the memory system.

The memory system allows the CPU to access cores in different ways given the current execution mode. There are two execution modes - firmware and application. Basically, in application mode the access is more restrictive.

The rest of the components are under cores. They typically have their own README.md file documenting them and their API in detail.

Hardware functions with APIs, assets, and input/output are memory mapped starting at base address 0xc000_0000. For specific offsets and bitmasks, see the file fw/tk1_mem.h.

Rough memory map:

name prefix
ROM 0x00
RAM 0x40
TRNG 0xc0
Timer 0xc1
UDS 0xc2
UART 0xc3
Touch 0xc4
FW_RAM 0xd0
TK1 0xff

clk_reset_gen

Generator for system clock and system reset.

The device does not rely on external clock or reset. Instead the internal HFOSC oscillator combined with an internal PLL is used to generate the main clock. Currently the clock frequency driving the SoC is 21 MHz.

The device also generates its own reset.

fw_ram

Special firmware-only RAM. Unreachable from app mode.

picorv32

A softcore 32 bit RISC-V CPU from upstreams PicoRV32.

Configuration of optional CPU features like ENABLE_FAST_MUL et cetera are in rtl/application_fpga.v.

The instance enables the following features

  • Compressed ISA (C extension)
  • Fast multiplication. Two cycles for 32x32 multiplication
  • Barrel shifter

No other modification to the core has been done. No interrupts are used.

ram

The 128 KByte main RAM. The RAM is only used by applications. The memory is cleared by firmware before an application is loaded.

The application RAM is available to use by firmware and applications.

MC: Is the scrambling here now?

rom

ROM for the firmware. The firmware.elf minus the ELF header is embedded here in the bitstream.

After reset the CPU will initialize the program counter to start of ROM.

timer

A general purpose 32 bit timer. The timer will count down from the initial value to one. In order to handle long time sequences (minutes, hours, days) there is also a 32 bit prescaler.

The timer is available to use by firmware and applications.

tk1

See tk1 README for details.

Contains:

  • FPGA name and version.
  • Execution mode control: firmware mode/application mode.
  • RGB LED control.
  • General purpose input/output (GPIO) pin control.
  • Application introspection: start address and size of binary.
  • BLAKE2s function access.
  • Compound Device Identity (CDI).
  • Unique Device Identity (UDI).
  • RAM memory protection.
  • Security monitor.
  • SPI main.
  • System reset.

Illegal instruction monitor

Execution of illegal instructions will cause the CPU to enter its trap state from which it can't exit. The hardware in the TKey will monitor the CPU state. If the CPU enters the trap state, the hardware will start flashing the RED led, signalling that the TKey is stuck in an error state.

RAM memory protection

The TKey hardware includes a simple form of RAM memory protection. The purpose of the RAM memory protection is to make it somewhat harder and more time consuming to extract application assets by dumping the RAM contents from a TKey device. The memory protection is not based on encryption and should not be confused with real encryption. The protection is randomised between power cycles. The randomisation should make it infeasible to improve asset extraction by observing multiple memory dumps from the same TKey device. The attack should also not directly scale to multiple TKey devices.

The memory protection is based on two separate mechanisms:

  1. Address randomisation
  2. Address dependent data randomization

The address randomization is implemented by XORing the CPU address with the contents of the ADDR_RAM_ADDR_RAND register in the tk1 core. The result is used as the RAM address

The data randomization is implemented by XORing the data written to the RAM with the contents of the ADDR_RAM_DATA_RAND register in the tk1 core as well as XORing with the CPU address. This means that the same data written to two different addresses will be scrambled differently. The same pair or XOR operations is also performed on the data read out from the RAM.

The memory protection is setup by the firmware. Access to the memory protection controls is disabled for applications. Before the memory protecetion is enabled, the RAM is filled with randomised data using Xorwow. So during boot the firmware perform the following steps to setup the memory protection:

  1. Get a random 32-bit value from the TRNG to use as data state for Xorwow.
  2. Get a random 32-bit value from the TRNG to use as accumulator for Xorwow.
  3. Fill RAM with a random sequence of values by writing to all RAM addresses. For each address use Xorwow to generate a new state, using the accumulator.
  4. Write a random 32-bit value from the TRNG into the ADDR_RAM_ADDR_RAND register.
  5. Write a random 32-bit value from the TRNG into the ADDR_RAM_DATA_RAND register.
  6. Receive the application sent from the client and write it in sequence into RAM.

Future TKey devices may implement a more secure ASLR mechanism, and use real encryption (for example PRINCE) for memory content protection. From the application point of view such a change will be transparent.

touch_sense

Provide touch sensor events to software.

It is recommended that software start by acknowledge any stray events prior to signalling to the user that a touch event is expected and then start waiting for an event.

The touch sensor is available to use by firmware and applications.

trng

Provide a True Random Number Generator to software.

The TRNG generates entropy with a fairly good quality. However for security related use cases, for example key generation, the TRNG should not be used directly. Instead use it to create a seed, and reseed as necessary, for a Digital Random Bit Generator (DRBG), also known as a Cryptographically Safe Pseudo Random Number Generator (CSPRNG). Examples of such generators are Hash_DRGG, CTR_DRBG, and HKDF.

uart

A simple universal asynchronous receiver/transmitter (UART) used for communication with the client through the USB controller.

The UART default speed is 62500 bps, but can be adjusted by the application. (Note that the host must set the same bitrate too.)

The UART contain a 512 but Rx-FIFO with status (data available).

The UART is available to use by firmware and applications.

uds

The Unique Device Secret. During build initial value is taken from data/uds.hex.

However, with the finished bitstream you can patch in another UDS and UDI by using tools/patch_uds_udi.py with nextpnr.

It's a 256 bit memory implemented using eight 32-bit registers. The registers can only be accessed once between power cycling. This means that the UDS must be read as u32. If read as u8, only the first byte from a given address will be correct, subsequent bytes will be zero.

The UDS can only be read in firmware mode. Reading from the UDS in application mode will return all zeros.

References

More detailed information about the firmware running on the device can be found in the hw/application_fpga/fw/README.md.