doc: Update documentation about syscalls

- Revise firmware implementation notes
- Document how to do fw syscalls
  - Document how to trigger a syscall function in the firmware, how to
    pass arguments, what the caller is responsible for and what is
    returned.
- Describe hardware syscall implementation
  - how the syscall interrupts are triggered,
  - the hardware privilege escalation,
  - the UDS protection.

Co-authored-by: Daniel Jobson <jobson@tillitis.se>
Co-authored-by: Michael Cardell Widerkrantz <mc@tillitis.se>
This commit is contained in:
Mikael Ågren 2025-02-26 07:03:56 +01:00
parent 7554787678
commit c52442b54c
No known key found for this signature in database
GPG Key ID: E02DA3D397792C46
4 changed files with 161 additions and 120 deletions

View File

@ -11,9 +11,10 @@ The design top level is in `rtl/application_fpga.v`. It contains
instances of all cores as well as the memory system. instances of all cores as well as the memory system.
The memory system allows the CPU to access cores in different ways The memory system allows the CPU to access cores in different ways
given the current execution mode. There are two execution modes - given the current execution mode. There are three execution modes -
firmware and application. Basically, in application mode the access is firmware, application and system call. Each mode give access to a
more restrictive. different set of resources. Where app mode is the most restrictive and
firmware mode is the least restrictive.
The rest of the components are under `cores`. They typically have The rest of the components are under `cores`. They typically have
their own `README.md` file documenting them and their API in detail. their own `README.md` file documenting them and their API in detail.
@ -34,6 +35,7 @@ Rough memory map:
| UART | 0xc3 | | UART | 0xc3 |
| Touch | 0xc4 | | Touch | 0xc4 |
| FW\_RAM | 0xd0 | | FW\_RAM | 0xd0 |
| Syscall | 0xe1 |
| TK1 | 0xff | | TK1 | 0xff |
## `clk_reset_gen` ## `clk_reset_gen`
@ -96,6 +98,54 @@ hours, days) there is also a 32 bit prescaler.
The timer is available to use by firmware and applications. The timer is available to use by firmware and applications.
## Syscall
System call trigger area. A 32-bit write to address 0xe1000000 will
trigger interrupt 31, which in turn triggers a system call in the
firmware.
## Interrupts
Triggering an interrupt will cause the CPU to execute the interrupt
handler att address 0x10.
The interrupt handler is shared by all PicoRV32 interrupts but only
interrupt 31 is enabled on the Tkey. Register `x4` can be inspected to
determine the interrupt source. Each interrupt source is assigned one
bit in x4. Triggered interrupts have their bit set to `1`.
| *Source* | *x4 Bit* |
|----------|----------|
| Syscall | 31 |
The return address is located in register `x3`. Calling the PicoRV32
specific instruction `retirq` exits the interrupt handler and clears
the interrupt source.
No registers are stored/restored when entering/exiting the interrupt
handler. It is up to the software to store/restore as necessary.
Interrupts can be enabled/disabled using the PicoRV32 specific
`maskirq` instruction.
## Restricted resources
The following table shows resource availablility for each execution
mode:
| *Execution Mode* | *ROM* | *FW RAM* | *SPI* | *UDS* |
|------------------|-------|----------|-------|-------|
| Firmware mode | r/x | r/w | r/w | r/w* |
| Syscall | r/x | r/w | r/w | i |
| Application mode | r | i | i | i |
Legend:
r = readable
w = writeable
x = executable
i = invisible
* = UDS words are readable only once in firmware mode.
## `tk1` ## `tk1`
See [tk1 README](core/tk1/README.md) for details. See [tk1 README](core/tk1/README.md) for details.
@ -107,7 +157,6 @@ Contains:
- RGB LED control. - RGB LED control.
- General purpose input/output (GPIO) pin control. - General purpose input/output (GPIO) pin control.
- Application introspection: start address and size of binary. - Application introspection: start address and size of binary.
- BLAKE2s function access.
- Compound Device Identity (CDI). - Compound Device Identity (CDI).
- Unique Device Identity (UDI). - Unique Device Identity (UDI).
- RAM memory protection. - RAM memory protection.
@ -135,13 +184,13 @@ should make it infeasible to improve asset extraction by observing
multiple memory dumps from the same TKey device. The attack should multiple memory dumps from the same TKey device. The attack should
also not directly scale to multiple TKey devices. also not directly scale to multiple TKey devices.
The RAM address and data scrambling is done in de RAM core. The RAM address and data scrambling is done in the RAM core.
The memory protection is setup by the firmware. Access to the memory The memory protection is setup by the firmware. Access to the memory
protection controls is disabled for applications. Before the memory protection controls is disabled for applications. Before the memory
protecetion is enabled, the RAM is filled with randomised data using protecetion is enabled, the RAM is filled with randomised data using
Xorwow. So during boot the firmware perform the following steps to Xorwow. During boot the firmware perform the following steps to setup
setup the memory protection: the memory protection:
1. Get a random 32-bit value from the TRNG to use as data state for 1. Get a random 32-bit value from the TRNG to use as data state for
Xorwow. Xorwow.

View File

@ -23,17 +23,6 @@ and version of the device. They can be read by FW as well as
applications. applications.
### Control of execution mode
```
ADDR_APP_MODE_CTRL: 0x08
```
This register controls if the device is executing in FW mode or in App
mode. The register can be written once between power cycles, and only
by FW. If set the device is in app mode.
### Control of RGB LED ### Control of RGB LED
``` ```
@ -75,19 +64,7 @@ ADDR_APP_SIZE: 0x0d
These registers provide read only information to the loaded app to These registers provide read only information to the loaded app to
itself - where it was loaded and its size. The values are written by itself - where it was loaded and its size. The values are written by
FW as part of the loading of the app. The registers can't be written FW as part of the loading of the app. The registers can't be written
when the `ADDR_APP_MODE_CTRL` has been set. in application mode.
### Access to Blake2s
```
ADDR_BLAKE2S: 0x10
```
This register provides the 32-bit function pointer address to the
Blake2s hash function in the FW. It is written by FW during boot. The
register can't be written to when the `ADDR_APP_MODE_CTRL` has been
set.
### Access to CDI ### Access to CDI
@ -99,10 +76,10 @@ ADDR_CDI_LAST: 0x27
These registers provide access to the 256-bit compound device secret These registers provide access to the 256-bit compound device secret
calculated by the FW as part of loading an application. The registers calculated by the FW as part of loading an application. The registers
are written by the FW. The register can't be written to when the are written by the FW. The register can't be written in application
`ADDR_APP_MODE_CTRL` has been set. The CDI is readable by apps, which mode. The CDI is readable by apps, which can then use it as a base
can then use it as a base secret for any other secrets required to secret for any other secrets required to carry out their intended use
carry out their intended use case. case.
### Access to UDI ### Access to UDI

View File

@ -6,8 +6,7 @@ Unique Device Secret core
This core store and protect the Unique Device Secret (UDS) asset. The 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 only UDS can be accessed as eight separate 32-bit words. The words can only
be accessed as long as the app_mode input is low, implying that the be accessed as long as the `en` input is high.
CPU is executing the FW.
The UDS words can be accessed in any order, but a given word can only 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 be accessed once between reset cycles. This read once functionality is

View File

@ -1,35 +1,43 @@
# Firmware # Firmware implementation notes
## Introduction ## Introduction
This text is an introduction to, a requirement specification of, This text is specific for the firmware, the piece of software in TKey
and some implementation notes of the TKey firmware. It also gives a ROM. For a more general description on how to implement device apps,
few hint on developing and debugging the firmware. see [the TKey Developer Handbook](https://dev.tillitis.se/).
This text is specific for the firmware. For a more general description
on how to implement device apps, see [the TKey Developer
Handbook](https://dev.tillitis.se/).
## Definitions ## Definitions
- Firmware - software in ROM responsible for loading applications. The - Firmware: Software in ROM responsible for loading, measuring, and
firmware is included as part of the FPGA bitstream and not starting applications. The firmware is included as part of the FPGA
replacable on a usual consumer TKey. bitstream and not replacable on a usual consumer TKey.
- Device application or app - software supplied by the client which is - Client: Software running on a computer or a mobile phone the TKey is
received, loaded, measured, and started by the firmware. inserted into.
- Device application or app: Software supplied by the client that runs
on the TKey.
## CPU modes and firmware ## CPU modes and firmware
The TKey has two modes of software operation: firmware mode and The TKey has two modes of software operation: firmware mode and
application mode. The TKey always starts in firmware mode and starts application mode. The TKey always starts in firmware mode when it
the firmware. When the firmware is about to start the application it starts the firmware. When the application starts the hardware
switches to a more constrained environment, the application mode. automatically switches to a more constrained environment: the
application mode.
The TKey hardware cores are memory mapped. Firmware has complete The TKey hardware cores are memory mapped but the memory access is
access, except that the UDS is readable only once. The memory map is different depending on mode. Firmware has complete access, except that
constrained when running in application mode, e.g. FW\_RAM and UDS the Unique Device Secret (UDS) words are readable only once even in
isn't readable, and several other hardware addresses are either not firmware mode. The memory map is constrained when running in
readable or not writable for the application. application mode, e.g. FW\_RAM and UDS isn't readable, and several
other hardware addresses are either not readable or not writable for
the application.
When doing system calls from a device app the context switches back to
firmware mode. However, the UDS is still not available, protected by
two measures: 1) the UDS words can only be read out once and have
already been read by firmware when measuring the app, and, 2) the UDS
is protected by hardware after the execution leaves ROM for the first
time.
See the table in [the Developer See the table in [the Developer
Handbook](https://dev.tillitis.se/memory/) for an overview about the Handbook](https://dev.tillitis.se/memory/) for an overview about the
@ -72,12 +80,17 @@ Dev Handbook for specific details.
## Memory constraints ## Memory constraints
- ROM: 6 kByte. | *Name* | *Size* | *FW mode* | *App mode* |
- FW\_RAM: 4 kByte. |---------|-----------|-----------|------------|
- fw stack: 3824 bytes. | ROM | 8 kByte | r-x | r |
- resetinfo: 256 bytes. | FW\_RAM | 4 kByte* | rw- | - |
- rest is available for .data and .bss. | RAM | 128 kByte | rwx | rwx |
- RAM: 128 kByte.
* FW\_RAM is divided into the following areas:
- fw stack: 3824 bytes.
- resetinfo: 256 bytes.
- rest is available for .data and .bss.
## Firmware behaviour ## Firmware behaviour
@ -87,7 +100,7 @@ application received from the client over the USB/UART.
The firmware binary is part of the FPGA bitstream as the initial The firmware binary is part of the FPGA bitstream as the initial
values of the Block RAMs used to construct the `FW_ROM`. The `FW_ROM` values of the Block RAMs used to construct the `FW_ROM`. The `FW_ROM`
start address is located at `0x0000_0000` in the CPU memory map, which start address is located at `0x0000_0000` in the CPU memory map, which
is the CPU reset vector. is also the CPU reset vector.
### Firmware state machine ### Firmware state machine
@ -151,26 +164,30 @@ is received, when state is changed to "running".
In "running", the loaded device app is measured, the Compound Device In "running", the loaded device app is measured, the Compound Device
Identifier (CDI) is computed, we do some cleanup of firmware data Identifier (CDI) is computed, we do some cleanup of firmware data
structures, flip to application mode, and finally start the app, which structures, enable the system calls, and finally start the app, which
ends the firmware state machine. ends the firmware state machine. Hardware guarantees that we leave
firmware mode automatically when the program counter leaves ROM.
The device app is now running in application mode. There is no other The device app is now running in application mode. We can, however,
means of getting back from application mode to firmware mode than return to firmware mode (excepting access to the UDS) by doing system
resetting/power cycling the device. Note that ROM is still accessible calls. Note that ROM is still readable, but is now hardware protected
in the memory map, so it's still possible to execute firmware code in from execution, except through the system call mechanism.
application mode, but with no privileged access.
### Golden path
Firmware loads the application at the start of RAM (`0x4000_0000`). It Firmware loads the application at the start of RAM (`0x4000_0000`). It
use a part of the special FW\_RAM for its own stack. use a part of the special FW\_RAM for its own stack.
When reset is released, the CPU starts executing the firmware. It When reset is released, the CPU starts executing the firmware. It
begins by clearing all CPU registers, clears all FW\_RAM, sets up a begins in `start.S` by clearing all CPU registers, clears all FW\_RAM,
stack for itself there, and then jumps to `main()`. sets up a stack for itself there, and then jumps to `main()`. Also
included in the assembly part of firmware is an interrupt handler for
the system calls, but the handler is not yet enabled.
Beginning at `main()` it sets up the "system calls", then fills the Beginning at `main()` it fills the entire RAM with pseudo random data
entire RAM with pseudo random data and setting up the RAM address and and setting up the RAM address and data hardware scrambling with
data hardware scrambling with values from the True Random Number values from the True Random Number Generator (TRNG). It then waits for
Generator (TRNG). It then waits for data coming in through the UART. data coming in through the UART.
Typical expected use scenario: Typical expected use scenario:
@ -199,7 +216,7 @@ Typical expected use scenario:
([CDI]((#compound-device-identifier-computation))) is then ([CDI]((#compound-device-identifier-computation))) is then
computed by doing a new BLAKE2s using the Unique Device Secret computed by doing a new BLAKE2s using the Unique Device Secret
(UDS), the application digest, and any User Supplied Secret (UDS), the application digest, and any User Supplied Secret
(USS). (USS) digest already received.
6. The start address of the device app, currently `0x4000_0000`, is 6. The start address of the device app, currently `0x4000_0000`, is
written to `APP_ADDR` and the size of the binary to `APP_SIZE` to written to `APP_ADDR` and the size of the binary to `APP_SIZE` to
@ -207,24 +224,22 @@ Typical expected use scenario:
it is, if it wants to relocate in RAM. it is, if it wants to relocate in RAM.
7. The firmware now clears the part of the special `FW_RAM` where it 7. The firmware now clears the part of the special `FW_RAM` where it
keeps it stack. After this it performs no more function calls and keeps it stack.
uses no more automatic variables.
8. Firmware starts the application by first switching from firmware 8. The interrupt handler for system calls is enabled.
mode to application mode by writing to the `APP_MODE_CTRL`
register. In this mode the MMIO region is restricted, e.g. some 9. Firmware starts the application by jumping to the contents of
registers are removed (`UDS`), and some are switched from `APP_ADDR`. Hardware automatically switches from firmware mode to
read/write to read-only (see [the memory application mode. In this mode some memory access is restricted,
e.g. some addresses are inaccessible (`UDS`), and some are
switched from read/write to read-only (see [the memory
map](https://dev.tillitis.se/memory/)). map](https://dev.tillitis.se/memory/)).
Then the firmware jumps to what is in `APP_ADDR` which starts the
application.
If during this whole time any commands are received which are not If during this whole time any commands are received which are not
allowed in the current state, we enter the "failed" state and execute allowed in the current state, or any errors occur, we enter the
an illegal instruction. An illegal instruction traps the CPU and "failed" state and execute an illegal instruction. An illegal
hardware blinks the status LED red until a power cycle. No further instruction traps the CPU and hardware blinks the status LED red until
instructions are executed. a power cycle. No further instructions are executed.
### User-supplied Secret (USS) ### User-supplied Secret (USS)
@ -256,42 +271,43 @@ call `blake2s_update()` with it and then immediately call
`blake2s_update()` again with the program digest, destroying the UDS `blake2s_update()` again with the program digest, destroying the UDS
stored in the internal context buffer. UDS should now not be in stored in the internal context buffer. UDS should now not be in
`FW_RAM` anymore. We can read UDS only once per power cycle so UDS `FW_RAM` anymore. We can read UDS only once per power cycle so UDS
should now not be available to firmware at all. should now not be available even to firmware.
Then we continue with the CDI computation by updating with an optional Then we continue with the CDI computation by updating with an optional
USS and then finalizing the hash, storing the resulting digest in USS digest and finalizing the hash, storing the resulting digest in
`CDI`. `CDI`.
### Firmware services ### Firmware system calls
The firmware exposes a BLAKE2s function through a function pointer The firmware provides a system call mechanism through the use of the
located in MMIO `BLAKE2S` (see [memory PicoRV32 interrupt handler. They are triggered by writing to the
map](system_description.md#memory-mapped-hardware-functions)) with the trigger address: 0xe1000000. It's typically done with a function
with function signature: signature like this:
```c
int blake2s(void *out, unsigned long outlen, const void *key,
unsigned long keylen, const void *in, unsigned long inlen,
blake2s_ctx *ctx);
``` ```
int syscall(uint32_t number, uint32_t arg1);
where `blake2s_ctx` is:
```c
typedef struct {
uint8_t b[64]; // input buffer
uint32_t h[8]; // chained state
uint32_t t[2]; // total number of bytes
size_t c; // pointer for b[]
size_t outlen; // digest size
} blake2s_ctx;
``` ```
The `libcommon` library in Arguments are system call number and upto 6 generic arguments passed
[tkey-libs](https://github.com/tillitis/tkey-libs/) to the system call handler. The caller should place the system call
has a wrapper for using this function called `blake2s()` which needs number in the a0 register and the arguments in registers a1 to a7
to be maintained if you do any changes to the firmware call. according to the RISC-V calling convention. The caller is responsible
for saving and restoring registers.
The syscall handler returns execution on the next instruction after
the store instruction to the trigger address. The return value from
the syscall is now available in x10 (a0).
To add or change syscalls, see the `syscall_handler()` in
`syscall_handler.c`.
Currently supported syscalls:
| *Name* | *Number* | *Argument* | *Description* |
|-------------|----------|------------|----------------------------------|
| RESET | 1 | Unused | Reset the TKey |
| SET\_LED | 10 | Colour | Set the colour of the status LED |
| GET\_VIDPID | 12 | Unused | Get Vendor and Product ID |
## Developing firmware ## Developing firmware