mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-09-22 05:44:43 -04:00
tkey-libs: Import tag fw-5 of tkey-libs
Use tag fw-5 from https://github.com/tillitis/tkey-libs/
This commit is contained in:
parent
17e5e77187
commit
34e9f0a314
9 changed files with 310 additions and 8 deletions
|
@ -31,9 +31,9 @@ LDFLAGS=-T app.lds -L libcommon/ -lcommon -L libcrt0/ -lcrt0
|
|||
|
||||
|
||||
.PHONY: all
|
||||
all: libcrt0.a libcommon.a libmonocypher.a libblake2s.a
|
||||
all: libcrt0.a libcommon.a libsyscall.a libmonocypher.a libblake2s.a
|
||||
|
||||
IMAGE=ghcr.io/tillitis/tkey-builder:4
|
||||
IMAGE=ghcr.io/tillitis/tkey-builder:5rc1
|
||||
|
||||
podman:
|
||||
podman run --rm --mount type=bind,source=$(CURDIR),target=/src \
|
||||
|
@ -47,6 +47,14 @@ check:
|
|||
libcrt0.a: libcrt0/crt0.o
|
||||
$(AR) -qc $@ libcrt0/crt0.o
|
||||
|
||||
# System calls
|
||||
SYSCALLOBJS=libsyscall/syscall.o libsyscall/sys_wrapper.o
|
||||
|
||||
libsyscall.a: $(SYSCALLOBJS)
|
||||
$(AR) -qc $@ $(SYSCALLOBJS)
|
||||
|
||||
$(SYSCALLOBJS): include/tkey/syscall.h
|
||||
|
||||
# Common C functions
|
||||
LIBOBJS=libcommon/assert.o libcommon/led.o libcommon/lib.o \
|
||||
libcommon/proto.o libcommon/touch.o libcommon/io.o
|
||||
|
@ -69,13 +77,14 @@ libblake2s.a: $(B2OBJS)
|
|||
$(AR) -qc $@ $(B2OBJS)
|
||||
$B2OBJS: blake2s/blake2s.h
|
||||
|
||||
LIBS=libcrt0.a libcommon.a
|
||||
LIBS=libcrt0.a libcommon.a libsyscall.a
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(LIBS) $(LIBOBJS) libcrt0/crt0.o
|
||||
rm -f libmonocypher.a $(MONOOBJS)
|
||||
rm -f libblake2s.a $(B2OBJS)
|
||||
rm -f libsyscall.a $(SYSCALLOBJS)
|
||||
|
||||
# Create compile_commands.json for clangd and LSP
|
||||
.PHONY: clangd
|
||||
|
@ -85,7 +94,7 @@ compile_commands.json:
|
|||
bear -- make all
|
||||
|
||||
# Uses ../.clang-format
|
||||
FMTFILES=include/tkey/*.h libcommon/*.c
|
||||
FMTFILES=include/tkey/*.h libsyscall/*.c libcommon/*.c
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# Device libraries for the Tillitis TKey
|
||||
|
||||
- C runtime: libcrt0.
|
||||
- System call support: libsyscall.
|
||||
- Common C functions including protocol calls: libcommon.
|
||||
- Cryptographic functions: libmonocypher. Based on
|
||||
[Monocypher](https://github.com/LoupVaillant/Monocypher) version
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
- NOTE WELL! Rewritten I/O functions with new signatures and
|
||||
semantics!
|
||||
- `blake2s()` with new signature.
|
||||
- System call support.
|
||||
|
||||
### BLAKE2s hash function
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ path = [
|
|||
"Makefile",
|
||||
"README-DIST.txt",
|
||||
"README.md",
|
||||
"RELEASE.md"
|
||||
"RELEASE.md",
|
||||
]
|
||||
SPDX-FileCopyrightText = "2022 Tillitis AB <tillitis.se>"
|
||||
SPDX-License-Identifier = "BSD-2-Clause"
|
||||
|
|
|
@ -37,6 +37,6 @@ void puthex(enum ioend dest, const uint8_t ch);
|
|||
void putinthex(enum ioend dest, const uint32_t n);
|
||||
void puts(enum ioend dest, const char *s);
|
||||
void hexdump(enum ioend dest, void *buf, int len);
|
||||
void config_endpoints(enum ioend endpoints);
|
||||
void config_endpoints(uint8_t endpoints);
|
||||
|
||||
#endif
|
||||
|
|
63
hw/application_fpga/tkey-libs/include/tkey/syscall.h
Normal file
63
hw/application_fpga/tkey-libs/include/tkey/syscall.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef TKEY_SYSCALL_H
|
||||
#define TKEY_SYSCALL_H
|
||||
|
||||
#define RESET_DIGEST_SIZE 32
|
||||
#define RESET_DATA_SIZE 220
|
||||
|
||||
// Needs to be held synchronized with syscall_num.h in firmware.
|
||||
enum reset_start {
|
||||
START_DEFAULT = 0, // Probably cold boot
|
||||
START_FLASH0 = 1,
|
||||
START_FLASH1 = 2,
|
||||
START_FLASH0_VER = 3,
|
||||
START_FLASH1_VER = 4,
|
||||
START_CLIENT = 5,
|
||||
START_CLIENT_VER = 6,
|
||||
};
|
||||
|
||||
struct reset {
|
||||
enum reset_start type;
|
||||
uint8_t app_digest[RESET_DIGEST_SIZE];
|
||||
uint8_t next_app_data[RESET_DATA_SIZE];
|
||||
};
|
||||
|
||||
// Needs to be held synchronized with syscall_num.h in firmware.
|
||||
enum syscall_num {
|
||||
TK1_SYSCALL_RESET = 1,
|
||||
TK1_SYSCALL_ALLOC_AREA = 2,
|
||||
TK1_SYSCALL_DEALLOC_AREA = 3,
|
||||
TK1_SYSCALL_WRITE_DATA = 4,
|
||||
TK1_SYSCALL_READ_DATA = 5,
|
||||
TK1_SYSCALL_ERASE_DATA = 6,
|
||||
TK1_SYSCALL_GET_VIDPID = 7,
|
||||
TK1_SYSCALL_PRELOAD_STORE = 8,
|
||||
TK1_SYSCALL_PRELOAD_STORE_FIN = 9,
|
||||
TK1_SYSCALL_PRELOAD_DELETE = 10,
|
||||
TK1_SYSCALL_PRELOAD_GET_DIGSIG = 11,
|
||||
TK1_SYSCALL_REG_MGMT = 12,
|
||||
TK1_SYSCALL_STATUS = 13,
|
||||
TK1_SYSCALL_GET_APP_DATA = 14,
|
||||
};
|
||||
|
||||
int syscall(uint32_t number, uint32_t arg1, uint32_t arg2, uint32_t arg3);
|
||||
int sys_reset(struct reset *rst, size_t len);
|
||||
int sys_reset_data(uint8_t next_app_data[RESET_DATA_SIZE]);
|
||||
int sys_alloc(void);
|
||||
int sys_dealloc(void);
|
||||
int sys_write(uint32_t offset, void *buf, size_t len);
|
||||
int sys_read(uint32_t offset, void *buf, size_t len);
|
||||
int sys_erase(uint32_t offset, size_t len);
|
||||
int sys_get_vidpid(void);
|
||||
int sys_preload_delete(void);
|
||||
int sys_preload_store(uint32_t offset, void *app, size_t len);
|
||||
int sys_preload_store_fin(size_t len, uint8_t digest[32],
|
||||
uint8_t signature[64]);
|
||||
int sys_get_digsig(uint8_t digest[32], uint8_t signature[64]);
|
||||
int sys_status(void);
|
||||
#endif
|
|
@ -367,11 +367,11 @@ void hexdump(enum ioend dest, void *buf, int len)
|
|||
// - IO_CDC
|
||||
// - IO_CH552
|
||||
//
|
||||
// Use like this:
|
||||
// Use like this in the bitmask:
|
||||
//
|
||||
// config_endpoints(IO_FIDO|IO_DEBUG)
|
||||
//
|
||||
void config_endpoints(enum ioend endpoints)
|
||||
void config_endpoints(uint8_t endpoints)
|
||||
{
|
||||
uint8_t cmdbuf[2] = {0};
|
||||
|
||||
|
|
145
hw/application_fpga/tkey-libs/libsyscall/sys_wrapper.c
Normal file
145
hw/application_fpga/tkey-libs/libsyscall/sys_wrapper.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
// SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <tkey/syscall.h>
|
||||
|
||||
// Reset the TKey. Leave the reset type (enum reset_start) in rst as
|
||||
// well as an optional app_digest, forcing firmware to only allow that
|
||||
// specific app digest, as well as some data to leave to the next app
|
||||
// in chain in next_app_data. Send the length of the next_app_data in len.
|
||||
//
|
||||
// The TKey is reset and firmware starts again.
|
||||
//
|
||||
// Returns non-zero on error.
|
||||
int sys_reset(struct reset *rst, size_t len)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_RESET, (uint32_t)rst, len, 0);
|
||||
}
|
||||
|
||||
// Fills in data left from previous app in the chain into
|
||||
// `next_app_data`. Buffer needs to be large enough to receive
|
||||
// RESET_DATA_SIZE bytes.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_reset_data(uint8_t next_app_data[RESET_DATA_SIZE])
|
||||
{
|
||||
return syscall(TK1_SYSCALL_GET_APP_DATA, (uint32_t)next_app_data, 0, 0);
|
||||
}
|
||||
|
||||
// Allocate a flash area for the current app. Must be done before sys_write()
|
||||
// or sys_read(). If the current app already has an area allocated no new
|
||||
// area will be allocated.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_alloc(void)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_ALLOC_AREA, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Free an already allocated flash area for the current app.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_dealloc(void)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_DEALLOC_AREA, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Write data in `buf` to the app's flash area at byte `offset` within
|
||||
// the area.
|
||||
//
|
||||
// Up to storage area size bytes can be written at once and `offset` must be a
|
||||
// multiple of 256 bytes.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_write(uint32_t offset, void *buf, size_t len)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_WRITE_DATA, offset, (uint32_t)buf, len);
|
||||
}
|
||||
|
||||
// Read `len` bytes into `buf` at byte `offset` from the app's flash
|
||||
// area.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_read(uint32_t offset, void *buf, size_t len)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_READ_DATA, offset, (uint32_t)buf, len);
|
||||
}
|
||||
|
||||
// Erase `len` bytes from `offset` within the area.
|
||||
//
|
||||
// Both `len` and `offset` must be a multiple of 4096 bytes.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_erase(uint32_t offset, size_t len)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_ERASE_DATA, offset, len, 0);
|
||||
}
|
||||
|
||||
// Returns the TKey Vendor and Product ID.
|
||||
int sys_get_vidpid(void)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_GET_VIDPID, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Delete the app in flash slot 1. Only available for the verified
|
||||
// management app.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_preload_delete(void)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_PRELOAD_DELETE, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Store an app, or possibly just a block of an app, from the `app`
|
||||
// buffer in flash slot 1 at byte `offset`.
|
||||
//
|
||||
// If you can't fit your entire app in the buffer, call
|
||||
// `sys_preload_store` many times as you receive the binary from the
|
||||
// client. Returns 0 on success.
|
||||
//
|
||||
// Up to preloaded app area size bytes can be written at once and `offset` must
|
||||
// be a multiple of 256 bytes.
|
||||
//
|
||||
// Only available for the verified management app.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_preload_store(uint32_t offset, void *app, size_t len)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_PRELOAD_STORE, offset, (uint32_t)app, len);
|
||||
}
|
||||
|
||||
// Finalize storing of an app where the complete binary size is `len`
|
||||
// in flash slot 1. Returns 0 on success. Only available for the
|
||||
// verified management app.
|
||||
//
|
||||
// Compute a BLAKE2s hash digest over the entire binary. Pass the
|
||||
// result in `app_digest`.
|
||||
//
|
||||
// Sign `app_digest` with your Ed25519 private key and pass the
|
||||
// resulting signature in `app_signature`.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_preload_store_fin(size_t len, uint8_t digest[32], uint8_t signature[64])
|
||||
{
|
||||
return syscall(TK1_SYSCALL_PRELOAD_STORE_FIN, len, (uint32_t)digest,
|
||||
(uint32_t)signature);
|
||||
}
|
||||
|
||||
// Copies the digest and signature of app in flash slot 1 to
|
||||
// `app_digest` and `app_signature`. Returns 0 on success. Only
|
||||
// available for the verified management app.
|
||||
//
|
||||
// Returns 0 on success.
|
||||
int sys_get_digsig(uint8_t digest[32], uint8_t signature[64])
|
||||
{
|
||||
return syscall(TK1_SYSCALL_PRELOAD_GET_DIGSIG, (uint32_t)digest,
|
||||
(uint32_t)signature, 0);
|
||||
}
|
||||
|
||||
// Returns filesystem status. Non-zero when problems have been
|
||||
// detected, so far only that the first copy of the partition table
|
||||
// didn't pass checks.
|
||||
int sys_status(void)
|
||||
{
|
||||
return syscall(TK1_SYSCALL_STATUS, 0, 0, 0);
|
||||
}
|
83
hw/application_fpga/tkey-libs/libsyscall/syscall.S
Normal file
83
hw/application_fpga/tkey-libs/libsyscall/syscall.S
Normal file
|
@ -0,0 +1,83 @@
|
|||
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
.section ".text"
|
||||
.globl syscall
|
||||
|
||||
|
||||
syscall:
|
||||
// Save registers to stack
|
||||
addi sp, sp, -32*4
|
||||
sw x0, 0*4(sp)
|
||||
sw x1, 1*4(sp)
|
||||
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||
sw x3, 3*4(sp)
|
||||
sw x4, 4*4(sp)
|
||||
sw x5, 5*4(sp)
|
||||
sw x6, 6*4(sp)
|
||||
sw x7, 7*4(sp)
|
||||
sw x8, 8*4(sp)
|
||||
sw x9, 9*4(sp)
|
||||
// x10 (a0) will contain syscall return value. And should not be saved.
|
||||
sw x11, 11*4(sp)
|
||||
sw x12, 12*4(sp)
|
||||
sw x13, 13*4(sp)
|
||||
sw x14, 14*4(sp)
|
||||
sw x15, 15*4(sp)
|
||||
sw x16, 16*4(sp)
|
||||
sw x17, 17*4(sp)
|
||||
sw x18, 18*4(sp)
|
||||
sw x19, 19*4(sp)
|
||||
sw x20, 20*4(sp)
|
||||
sw x21, 21*4(sp)
|
||||
sw x22, 22*4(sp)
|
||||
sw x23, 23*4(sp)
|
||||
sw x24, 24*4(sp)
|
||||
sw x25, 25*4(sp)
|
||||
sw x26, 26*4(sp)
|
||||
sw x27, 27*4(sp)
|
||||
sw x28, 28*4(sp)
|
||||
sw x29, 29*4(sp)
|
||||
sw x30, 30*4(sp)
|
||||
sw x31, 31*4(sp)
|
||||
|
||||
// Trigger syscall interrupt
|
||||
li t1, 0xe1000000 // Syscall interrupt trigger address
|
||||
sw zero, 0(t1) // Trigger interrupt
|
||||
|
||||
// Restore registers from stack
|
||||
lw x0, 0*4(sp)
|
||||
lw x1, 1*4(sp)
|
||||
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||
lw x3, 3*4(sp)
|
||||
lw x4, 4*4(sp)
|
||||
lw x5, 5*4(sp)
|
||||
lw x6, 6*4(sp)
|
||||
lw x7, 7*4(sp)
|
||||
lw x8, 8*4(sp)
|
||||
lw x9, 9*4(sp)
|
||||
// x10 (a0) contains syscall return value. And should not be destroyed.
|
||||
lw x11, 11*4(sp)
|
||||
lw x12, 12*4(sp)
|
||||
lw x13, 13*4(sp)
|
||||
lw x14, 14*4(sp)
|
||||
lw x15, 15*4(sp)
|
||||
lw x16, 16*4(sp)
|
||||
lw x17, 17*4(sp)
|
||||
lw x18, 18*4(sp)
|
||||
lw x19, 19*4(sp)
|
||||
lw x20, 20*4(sp)
|
||||
lw x21, 21*4(sp)
|
||||
lw x22, 22*4(sp)
|
||||
lw x23, 23*4(sp)
|
||||
lw x24, 24*4(sp)
|
||||
lw x25, 25*4(sp)
|
||||
lw x26, 26*4(sp)
|
||||
lw x27, 27*4(sp)
|
||||
lw x28, 28*4(sp)
|
||||
lw x29, 29*4(sp)
|
||||
lw x30, 30*4(sp)
|
||||
lw x31, 31*4(sp)
|
||||
addi sp, sp, 32*4
|
||||
|
||||
ret
|
Loading…
Add table
Add a link
Reference in a new issue