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:
Michael Cardell Widerkrantz 2025-09-01 17:43:05 +02:00
parent 17e5e77187
commit 34e9f0a314
No known key found for this signature in database
GPG key ID: D3DB3DDF57E704E5
9 changed files with 310 additions and 8 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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

View 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

View file

@ -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};

View 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);
}

View 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