mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2024-10-01 01:45:38 -04:00
fw: Add support for blake2s MMIO
In firmware we store the address to firmware blake2s() function at TK1_MMIO_TK1_BLAKE2S so app can use this firmware function sort of like a system call but without context switch.
This commit is contained in:
parent
a48dc7cbbb
commit
08e1438d1e
@ -418,6 +418,35 @@ host <-
|
||||
RSP[36..] = 0
|
||||
```
|
||||
|
||||
### Firmware services
|
||||
|
||||
The firmware exposes a BLAKE2s function through a function pointer
|
||||
located in MMIO `BLAKE2S` (see memory map below) with the with
|
||||
function signature:
|
||||
|
||||
```c
|
||||
int blake2s(void *out, unsigned long outlen, const void *key,
|
||||
unsigned long keylen, const void *in, unsigned long inlen,
|
||||
blake2s_ctx *ctx);
|
||||
|
||||
```
|
||||
|
||||
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
|
||||
[tillitis-key1-apps](https://github.com/tillitis/tillitis-key1-apps/)
|
||||
has a wrapper for using this function.
|
||||
|
||||
## Memory map
|
||||
|
||||
Assigned top level prefixes:
|
||||
@ -463,40 +492,41 @@ Assigned core prefixes:
|
||||
*Nota bene*: MMIO accesses should be 32 bit wide, e.g use `lw` and
|
||||
`sw`. Exceptions are `FW_RAM` and `QEMU_DEBUG`.
|
||||
|
||||
| *name* | *fw* | *app* | *size* | *type* | *content* | *description* |
|
||||
|-------------------|-------|-----------|--------|----------|-----------|------------------------------------------------------------------------|
|
||||
| `TRNG_STATUS` | r | r | | | | TRNG_STATUS_READY_BIT is 1 when an entropy word is available. |
|
||||
| `TRNG_ENTROPY` | r | r | 4B | u32 | | Entropy word. Reading a word will clear status. |
|
||||
| `TIMER_CTRL` | r/w | r/w | | | | If TIMER_STATUS_READY_BIT in TIMER_STATUS is 1, writing anything here |
|
||||
| | | | | | | starts the timer. If the same bit is 0 then writing stops the timer. |
|
||||
| `TIMER_STATUS` | r | r | | | | TIMER_STATUS_READY_BIT is 1 when timer is ready to start running. |
|
||||
| `TIMER_PRESCALER` | r/w | r/w | 4B | | | Prescaler init value. Write blocked when running. |
|
||||
| `TIMER_TIMER` | r/w | r/w | 4B | | | Timer init or current value while running. Write blocked when running. |
|
||||
| `UDS_FIRST` | r[^3] | invisible | 4B | u8[32] | | First word of Unique Device Secret key. |
|
||||
| `UDS_LAST` | | invisible | | | | The last word of the UDS |
|
||||
| `UART_BITRATE` | r/w | | | | | TBD |
|
||||
| `UART_DATABITS` | r/w | | | | | TBD |
|
||||
| `UART_STOPBITS` | r/w | | | | | TBD |
|
||||
| `UART_RX_STATUS` | r | r | 1B | u8 | | Non-zero when there is data to read |
|
||||
| `UART_RX_DATA` | r | r | 1B | u8 | | Data to read. Only LSB contains data |
|
||||
| `UART_TX_STATUS` | r | r | 1B | u8 | | Non-zero when it's OK to write data |
|
||||
| `UART_TX_DATA` | w | w | 1B | u8 | | Data to send. Only LSB contains data |
|
||||
| `TOUCH_STATUS` | r/w | r/w | | | | TOUCH_STATUS_EVENT_BIT is 1 when touched. After detecting a touch |
|
||||
| | | | | | | event (reading a 1), write anything here to acknowledge it. |
|
||||
| `FW_RAM` | r/w | invisible | 1 kiB | u8[1024] | | Firmware-only RAM. |
|
||||
| `UDA` | r | invisible | 16B | u8[16] | | Unique Device Authentication key. |
|
||||
| `UDI` | r | r | 8B | u64 | | Unique Device ID (UDI). |
|
||||
| `QEMU_DEBUG` | w | w | | u8 | | Debug console (only in QEMU) |
|
||||
| `NAME0` | r | r | 4B | char[4] | "tk1 " | ID of core/stick |
|
||||
| `NAME1` | r | r | 4B | char[4] | "mkdf" | ID of core/stick |
|
||||
| `VERSION` | r | r | 4B | u32 | 1 | Current version. |
|
||||
| `SWITCH_APP` | r/w | r | 1B | u8 | | Write anything here to trigger the switch to application mode. Reading |
|
||||
| | | | | | | returns 0 if device is in firmware mode, 0xffffffff if in app mode. |
|
||||
| `LED` | w | w | 1B | u8 | | |
|
||||
| `GPIO` | | | | | | |
|
||||
| `APP_ADDR` | r/w | r | 4B | u32 | | Firmware stores app load address here, so app can read its own location|
|
||||
| `APP_SIZE` | r/w | r | 4B | u32 | | Firmware stores app app size here, so app can read its own size |
|
||||
| `CDI_FIRST` | r/w | r | 32B | u8[32] | | Compound Device Identifier (CDI). UDS+measurement... |
|
||||
| `CDI_LAST` | | r | | | | Last word of CDI |
|
||||
| *name* | *fw* | *app* | *size* | *type* | *content* | *description* |
|
||||
|-------------------|-------|-----------|--------|----------|-----------|-------------------------------------------------------------------------|
|
||||
| `TRNG_STATUS` | r | r | | | | TRNG_STATUS_READY_BIT is 1 when an entropy word is available. |
|
||||
| `TRNG_ENTROPY` | r | r | 4B | u32 | | Entropy word. Reading a word will clear status. |
|
||||
| `TIMER_CTRL` | r/w | r/w | | | | If TIMER_STATUS_READY_BIT in TIMER_STATUS is 1, writing anything here |
|
||||
| | | | | | | starts the timer. If the same bit is 0 then writing stops the timer. |
|
||||
| `TIMER_STATUS` | r | r | | | | TIMER_STATUS_READY_BIT is 1 when timer is ready to start running. |
|
||||
| `TIMER_PRESCALER` | r/w | r/w | 4B | | | Prescaler init value. Write blocked when running. |
|
||||
| `TIMER_TIMER` | r/w | r/w | 4B | | | Timer init or current value while running. Write blocked when running. |
|
||||
| `UDS_FIRST` | r[^3] | invisible | 4B | u8[32] | | First word of Unique Device Secret key. |
|
||||
| `UDS_LAST` | | invisible | | | | The last word of the UDS |
|
||||
| `UART_BITRATE` | r/w | | | | | TBD |
|
||||
| `UART_DATABITS` | r/w | | | | | TBD |
|
||||
| `UART_STOPBITS` | r/w | | | | | TBD |
|
||||
| `UART_RX_STATUS` | r | r | 1B | u8 | | Non-zero when there is data to read |
|
||||
| `UART_RX_DATA` | r | r | 1B | u8 | | Data to read. Only LSB contains data |
|
||||
| `UART_TX_STATUS` | r | r | 1B | u8 | | Non-zero when it's OK to write data |
|
||||
| `UART_TX_DATA` | w | w | 1B | u8 | | Data to send. Only LSB contains data |
|
||||
| `TOUCH_STATUS` | r/w | r/w | | | | TOUCH_STATUS_EVENT_BIT is 1 when touched. After detecting a touch |
|
||||
| | | | | | | event (reading a 1), write anything here to acknowledge it. |
|
||||
| `FW_RAM` | r/w | invisible | 1 kiB | u8[1024] | | Firmware-only RAM. |
|
||||
| `UDA` | r | invisible | 16B | u8[16] | | Unique Device Authentication key. |
|
||||
| `UDI` | r | r | 8B | u64 | | Unique Device ID (UDI). |
|
||||
| `QEMU_DEBUG` | w | w | | u8 | | Debug console (only in QEMU) |
|
||||
| `NAME0` | r | r | 4B | char[4] | "tk1 " | ID of core/stick |
|
||||
| `NAME1` | r | r | 4B | char[4] | "mkdf" | ID of core/stick |
|
||||
| `VERSION` | r | r | 4B | u32 | 1 | Current version. |
|
||||
| `SWITCH_APP` | r/w | r | 1B | u8 | | Write anything here to trigger the switch to application mode. Reading |
|
||||
| | | | | | | returns 0 if device is in firmware mode, 0xffffffff if in app mode. |
|
||||
| `LED` | w | w | 1B | u8 | | |
|
||||
| `GPIO` | | | | | | |
|
||||
| `APP_ADDR` | r/w | r | 4B | u32 | | Firmware stores app load address here, so app can read its own location |
|
||||
| `APP_SIZE` | r/w | r | 4B | u32 | | Firmware stores app app size here, so app can read its own size |
|
||||
| `BLAKE2S` | r/w | r | 4B | u32 | | Function pointer to a BLAKE2S function in the firmware |
|
||||
| `CDI_FIRST` | r/w | r | 32B | u8[32] | | Compound Device Identifier (CDI). UDS+measurement... |
|
||||
| `CDI_LAST` | | r | | | | Last word of CDI |
|
||||
|
||||
[^3]: The UDS can only be read *once* per power-cycle.
|
||||
|
@ -84,7 +84,8 @@ TESTFW_OBJS = \
|
||||
$(P)/fw/testfw/main.o \
|
||||
$(P)/fw/tk1/start.o \
|
||||
$(P)/fw/tk1/proto.o \
|
||||
$(P)/fw/tk1/lib.o
|
||||
$(P)/fw/tk1/lib.o \
|
||||
$(P)/fw/tk1/blake2s/blake2s.o
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# All: Complete build of HW and FW.
|
||||
|
@ -3,26 +3,31 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#include "../tk1/blake2s/blake2s.h"
|
||||
#include "../tk1/lib.h"
|
||||
#include "../tk1/proto.h"
|
||||
#include "../tk1/types.h"
|
||||
#include "../tk1_mem.h"
|
||||
|
||||
// clang-format off
|
||||
volatile uint32_t *tk1name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
|
||||
volatile uint32_t *tk1name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
|
||||
volatile uint32_t *uds = (volatile uint32_t *)TK1_MMIO_UDS_FIRST;
|
||||
volatile uint32_t *uda = (volatile uint32_t *)TK1_MMIO_QEMU_UDA; // Only in QEMU right now
|
||||
volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
|
||||
volatile uint32_t *udi = (volatile uint32_t *)TK1_MMIO_TK1_UDI_FIRST;
|
||||
volatile uint32_t *switch_app = (volatile uint32_t *)TK1_MMIO_TK1_SWITCH_APP;
|
||||
volatile uint8_t *fw_ram = (volatile uint8_t *)TK1_MMIO_FW_RAM_BASE;
|
||||
volatile uint32_t *timer = (volatile uint32_t *)TK1_MMIO_TIMER_TIMER;
|
||||
volatile uint32_t *tk1name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
|
||||
volatile uint32_t *tk1name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
|
||||
volatile uint32_t *uds = (volatile uint32_t *)TK1_MMIO_UDS_FIRST;
|
||||
volatile uint32_t *uda = (volatile uint32_t *)TK1_MMIO_QEMU_UDA; // Only in QEMU right now
|
||||
volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
|
||||
volatile uint32_t *udi = (volatile uint32_t *)TK1_MMIO_TK1_UDI_FIRST;
|
||||
volatile uint32_t *switch_app = (volatile uint32_t *)TK1_MMIO_TK1_SWITCH_APP;
|
||||
volatile uint8_t *fw_ram = (volatile uint8_t *)TK1_MMIO_FW_RAM_BASE;
|
||||
volatile uint32_t *timer = (volatile uint32_t *)TK1_MMIO_TIMER_TIMER;
|
||||
volatile uint32_t *timer_prescaler = (volatile uint32_t *)TK1_MMIO_TIMER_PRESCALER;
|
||||
volatile uint32_t *timer_status = (volatile uint32_t *)TK1_MMIO_TIMER_STATUS;
|
||||
volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
|
||||
volatile uint32_t *trng_status = (volatile uint32_t *)TK1_MMIO_TRNG_STATUS;
|
||||
volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY;
|
||||
volatile uint32_t *timer_status = (volatile uint32_t *)TK1_MMIO_TIMER_STATUS;
|
||||
volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
|
||||
volatile uint32_t *trng_status = (volatile uint32_t *)TK1_MMIO_TRNG_STATUS;
|
||||
volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY;
|
||||
volatile uint32_t *fw_blake2s_addr = (volatile uint32_t *)TK1_MMIO_TK1_BLAKE2S;
|
||||
|
||||
// Function pointer to blake2s()
|
||||
volatile int (*fw_blake2s)(void *, unsigned long, const void *, unsigned long, const void *, unsigned long, blake2s_ctx *);
|
||||
// clang-format on
|
||||
|
||||
// TODO Real UDA is 4 words (16 bytes)
|
||||
@ -57,6 +62,23 @@ void puthexn(uint8_t *p, int n)
|
||||
}
|
||||
}
|
||||
|
||||
void hexdump(uint8_t *buf, int len)
|
||||
{
|
||||
uint8_t *row;
|
||||
uint8_t *byte;
|
||||
uint8_t *max;
|
||||
|
||||
row = buf;
|
||||
max = &buf[len];
|
||||
for (byte = 0; byte != max; row = byte) {
|
||||
for (byte = row; byte != max && byte != (row + 16); byte++) {
|
||||
puthex(*byte);
|
||||
}
|
||||
|
||||
puts("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void reverseword(uint32_t *wordp)
|
||||
{
|
||||
*wordp = ((*wordp & 0xff000000) >> 24) | ((*wordp & 0x00ff0000) >> 8) |
|
||||
@ -157,6 +179,9 @@ int main()
|
||||
anyfailed = 1;
|
||||
}
|
||||
|
||||
// Store function pointer to blake2s() so it's reachable from app
|
||||
*fw_blake2s_addr = (uint32_t)blake2s;
|
||||
|
||||
// Turn on application mode.
|
||||
// -------------------------
|
||||
*switch_app = 1;
|
||||
@ -238,6 +263,32 @@ int main()
|
||||
anyfailed = 1;
|
||||
}
|
||||
|
||||
// Testing the blake2s MMIO in app mode
|
||||
|
||||
fw_blake2s = (volatile int (*)(void *, unsigned long, const void *,
|
||||
unsigned long, const void *,
|
||||
unsigned long, blake2s_ctx *)) *
|
||||
fw_blake2s_addr;
|
||||
|
||||
char msg[17] = "dldlkjsdkljdslsdj";
|
||||
uint32_t digest0[8];
|
||||
uint32_t digest1[8];
|
||||
blake2s_ctx b2s_ctx;
|
||||
|
||||
blake2s(&digest0[0], 32, NULL, 0, &msg, 17, &b2s_ctx);
|
||||
fw_blake2s(&digest1[0], 32, NULL, 0, &msg, 17, &b2s_ctx);
|
||||
|
||||
puts("digest #0: \r\n");
|
||||
hexdump((uint8_t *)digest0, 32);
|
||||
|
||||
puts("digest #1: \r\n");
|
||||
hexdump((uint8_t *)digest1, 32);
|
||||
|
||||
if (!memeq(digest0, digest1, 32)) {
|
||||
puts("FAIL: Digests not the same\r\n");
|
||||
anyfailed = 1;
|
||||
}
|
||||
|
||||
// Check and display test results.
|
||||
if (anyfailed) {
|
||||
puts("Some test FAILED!\r\n");
|
||||
|
@ -10,17 +10,18 @@
|
||||
#include "types.h"
|
||||
|
||||
// clang-format off
|
||||
static volatile uint32_t *uds = (volatile uint32_t *)TK1_MMIO_UDS_FIRST;
|
||||
static volatile uint32_t *switch_app = (volatile uint32_t *)TK1_MMIO_TK1_SWITCH_APP;
|
||||
static volatile uint32_t *name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
|
||||
static volatile uint32_t *name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
|
||||
static volatile uint32_t *ver = (volatile uint32_t *)TK1_MMIO_TK1_VERSION;
|
||||
static volatile uint32_t *udi = (volatile uint32_t *)TK1_MMIO_TK1_UDI_FIRST;
|
||||
static volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
|
||||
static volatile uint32_t *app_addr = (volatile uint32_t *)TK1_MMIO_TK1_APP_ADDR;
|
||||
static volatile uint32_t *app_size = (volatile uint32_t *)TK1_MMIO_TK1_APP_SIZE;
|
||||
static volatile uint8_t *fw_ram = (volatile uint8_t *)TK1_MMIO_FW_RAM_BASE;
|
||||
static volatile uint32_t *led = (volatile uint32_t *)TK1_MMIO_TK1_LED;
|
||||
static volatile uint32_t *uds = (volatile uint32_t *)TK1_MMIO_UDS_FIRST;
|
||||
static volatile uint32_t *switch_app = (volatile uint32_t *)TK1_MMIO_TK1_SWITCH_APP;
|
||||
static volatile uint32_t *name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
|
||||
static volatile uint32_t *name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
|
||||
static volatile uint32_t *ver = (volatile uint32_t *)TK1_MMIO_TK1_VERSION;
|
||||
static volatile uint32_t *udi = (volatile uint32_t *)TK1_MMIO_TK1_UDI_FIRST;
|
||||
static volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
|
||||
static volatile uint32_t *app_addr = (volatile uint32_t *)TK1_MMIO_TK1_APP_ADDR;
|
||||
static volatile uint32_t *app_size = (volatile uint32_t *)TK1_MMIO_TK1_APP_SIZE;
|
||||
static volatile uint8_t *fw_ram = (volatile uint8_t *)TK1_MMIO_FW_RAM_BASE;
|
||||
static volatile uint32_t *led = (volatile uint32_t *)TK1_MMIO_TK1_LED;
|
||||
static volatile uint32_t *fw_blake2s_addr = (volatile uint32_t *)TK1_MMIO_TK1_BLAKE2S;
|
||||
|
||||
#define LED_RED (1 << TK1_MMIO_TK1_LED_R_BIT)
|
||||
#define LED_GREEN (1 << TK1_MMIO_TK1_LED_G_BIT)
|
||||
@ -149,6 +150,8 @@ int main()
|
||||
uint8_t uss[32] = {0};
|
||||
uint8_t digest[32] = {0};
|
||||
enum state state = FW_STATE_INITIAL;
|
||||
// Let the app know the function adddress for blake2s()
|
||||
*fw_blake2s_addr = (uint32_t)blake2s;
|
||||
|
||||
print_hw_version(namever);
|
||||
|
||||
|
@ -87,6 +87,7 @@ enum {
|
||||
TK1_MMIO_TK1_GPIO4_BIT = 3,
|
||||
TK1_MMIO_TK1_APP_ADDR = TK1_MMIO_TK1_BASE | 0x30,
|
||||
TK1_MMIO_TK1_APP_SIZE = TK1_MMIO_TK1_BASE | 0x34,
|
||||
TK1_MMIO_TK1_BLAKE2S = TK1_MMIO_TK1_BASE | 0x40,
|
||||
TK1_MMIO_TK1_CDI_FIRST = TK1_MMIO_TK1_BASE | 0x80,
|
||||
TK1_MMIO_TK1_CDI_LAST = TK1_MMIO_TK1_BASE | 0x9c, // Address of last 32-bit word of CDI.
|
||||
TK1_MMIO_TK1_UDI_FIRST = TK1_MMIO_TK1_BASE | 0xc0,
|
||||
|
Loading…
Reference in New Issue
Block a user