Compare commits

..

107 commits

Author SHA1 Message Date
Daniel Jobson
5f3a065aaa Follow REUSE specification
- Add REUSE configuration
- Add compliant licenses in LICENSES/
- Add copyright SPDX tags
- Run REUSE complicance check in CI
- Remove spdx-ensure
2025-10-30 13:07:59 +01:00
Daniel Jobson
c53edbe4ac gitignore: ignore all archives in tkey-libs 2025-10-30 13:07:59 +01:00
Daniel Jobson
a37f687881 Change license to BSD-2-Clause
This was announced on the Tillitis Blog the 2nd of October 2024, for
more info visit https://tillitis.se
2025-10-30 13:07:59 +01:00
Daniel Jobson
ea82b0c1fd Update application_fpga.bin.sha256 2025-10-28 08:40:06 +01:00
Daniel Jobson
afdbaf99fb ch552: Make CTS active low, as per the standard 2025-10-28 08:40:06 +01:00
Daniel Jobson
1a47a2266f uart: Make CTS active low, as per the standard 2025-10-28 08:40:06 +01:00
Daniel Jobson
74e3d74c11 fpga: Update next-pnr seed to reach 24 MHz 2025-10-27 15:13:12 +01:00
Daniel Jobson
6104356892 tb: uart add framing error test
- Adds option to test invalid stop bit
- Adds a test that simulates an always low rx line
2025-10-27 08:54:34 +01:00
Daniel Jobson
395d241ed3 uart: add framing error handling
- Checks the stop bit, if it is not valid the data is discarded and
  enters a error state. Only checks first stop bit.
- Adds an error state to the RX FSM. The core starts in this state to
  not assume a valid idle rx line on start up. Prevents accepting
  frames on a constant low rx line and filling the fifo.
- bugfix: always reset bitrate_ctr when leaving state ERX_BITS and
  remove unused bitrate_ctr counter in ERX_STOP
2025-10-27 08:54:31 +01:00
Michael Cardell Widerkrantz
aa04cf068f
doc: Add LICENSE file for picorv32 custom ops 2025-09-02 11:09:15 +02:00
Michael Cardell Widerkrantz
cbcb7fb1de
build: Run static code analysis after fw build
Since we now generate at least one source code file we need to run the
static code analysis after the build.
2025-09-02 11:09:15 +02:00
Michael Cardell Widerkrantz
34e9f0a314
tkey-libs: Import tag fw-5 of tkey-libs
Use tag fw-5 from https://github.com/tillitis/tkey-libs/
2025-09-02 11:09:12 +02:00
Michael Cardell Widerkrantz
17e5e77187
build: Always rebuild firmware if any header file changes 2025-09-01 18:19:54 +02:00
Michael Cardell Widerkrantz
18386b4865
build: Remove all built qemu artefacts when cleaning 2025-09-01 18:19:54 +02:00
Michael Cardell Widerkrantz
90a91ba1ba
build: Create and use a complete filesystem image
- Create a flash image in flash_image.bin, useful for both a real TKey
  and QEMU.

- Use flash_image.bin directly in prog_flash for a real TKey, which
  also flashes the bitstream.

- Remove building of tools/default_partition.bin.

- Update documentation about the tool use.

- We keep the load_preloaded_app.sh for development purposes,
  but it's no longer used in the build.
2025-09-01 18:19:54 +02:00
Michael Cardell Widerkrantz
65ff0a5d61
doc: Document the filesystem 2025-09-01 18:19:54 +02:00
Michael Cardell Widerkrantz
6fc4d264cc
build: Introduce DEFAULT_APP with automatic builds
Introduce the Makefile variable DEFAULT_APP which should be the path
to the device app binary to include in the obliagory slot 0.

Build automatically: the default app, the new digest file
mgmt_app_digest.h for the firmware which contains the digest of
DEFAULT_APP, the default partition table, and all the tools necessary
to generate this.
2025-09-01 18:19:54 +02:00
Michael Cardell Widerkrantz
9eed887a75
ci: Bump to tkey-builder:5rc2 2025-09-01 18:19:53 +02:00
Michael Cardell Widerkrantz
d3492e2a34
tool: Change b2s to output exact variable used
- Use correct name.
- Don't declare it as static.
- Lose the toolchain
- Use only basename of path in the b2s comment
2025-09-01 18:19:53 +02:00
Jonas Thörnblad
13767ee7df
Add loopbackapp for app debugging using physical TKey with QEMU
This app takes data coming in on any of the normal USB endpoints
like CDC and FIDO (or CCID) and outputs the data on the DEBUG
endpoint.

Using the scripts (tkey_to_udp_linux.py, tkey_to_udp_win.py) in
QEMU (tk1 branch) under tools/tk1, the data from the DEBUG
endpoint can be read and sent over the network to the script
udp_to_qemu_linux.py that feeds it to QEMU.
2025-08-28 17:01:07 +02:00
Jonas Thörnblad
1926d19146
fw: Change loader app
- Change loader app from testloadapp to defaultapp
- Update default_partition.bin to contain defaultapp.bin
2025-08-22 15:11:01 +02:00
Michael Cardell Widerkrantz
babdef52f5
toolchain: Add Go package
- Add Go 1.23.
- Set up PATH for container to include the Go binaries.
2025-07-17 07:53:50 +02:00
Jonas Thörnblad
a0f699aea5
Update USB product descriptor for Castor 2025-06-27 15:01:29 +02:00
Jonas Thörnblad
62adf4da71
Update USB VID and PID for Castor
VID has been wrong for some reason, therefore changed to the
correct value 0x1209.

New PID to differentiate Castor from Bellatrix.
2025-06-27 15:01:29 +02:00
Jonas Thörnblad
1a904e8857
Fix allowed_app_digest formatting
Fix formating of BLAKE2s digest of app allowed to start from
flash slot 0.
2025-06-27 15:01:29 +02:00
Jonas Thörnblad
03d96c3e96
tool: Fix b2s BLAKE2s digest zero padding 2025-06-24 18:18:17 +02:00
Jonas Thörnblad
c0b3c80620
Add make targets for building CH552 firmware with podman 2025-06-24 17:27:21 +02:00
Mikael Ågren
460d310c73
fw: Fix qemu_firmware build warnings 2025-06-19 08:50:13 +02:00
Michael Cardell Widerkrantz
f4f8c9e6c6
doc: Update Building & flashing docs
- Point out where to find tools.

- Add some description that we assume a Linux dist.

- Move the make targets around: make flash builds and flashes the
  entire thing so someone who just want to exactly that can use it
  right away.

- Explain what kind of hardware the USB controller is.

- Add a description on how to be able to use chprog without being
  root when running chprog.
2025-05-30 18:07:29 +02:00
Sasko Simonovski
ed9395c832
doc: Describe how to test alpha release in release notes
Adds information and link on how to test alpha release.
2025-05-28 11:56:22 +02:00
Mikael Ågren
888f18e5fe
doc: Refer to CH55x Reset Controller silk screen labels in flash docs 2025-05-26 07:59:50 +02:00
Michael Cardell Widerkrantz
24ef7b412b
doc: Add description on how to build and flash USB controller firmware 2025-05-23 15:43:44 +02:00
Michael Cardell Widerkrantz
f5d2cfef15
doc: Mention the tkeyimage tool in firmware README 2025-05-23 14:12:36 +02:00
Michael Cardell Widerkrantz
9a93da087d
doc: Document how to flash with filesystem 2025-05-23 14:12:36 +02:00
Michael Cardell Widerkrantz
916c37eab9
doc: Update release notes
Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-05-23 14:05:58 +02:00
Michael Cardell Widerkrantz
29e5888482
doc: Remove old toolchain setup text
Use current information in Developer Handbook,
https://dev.tillitis.se/ instead of relying on this old description.
2025-05-23 14:05:58 +02:00
Mikael Ågren
e8acc7aee2
build: Flash partition table when running make prog_flash
Changes make targets:

- prog_flash in hw/application/Makefile which flashes only the
  bitstream is renamed to prog_flash_bs.

- prog_flash in hw/application/Makefile is modified to flash the
  bitstream, the testloadapp.bin in app slot 0, and the partition table.

- flash in contrib/Makefile is modified to use prog_flash from
  hw/application/Makefile
2025-05-22 15:24:45 +02:00
Mikael Ågren
4172db8dfb
build: Do not use sudo when running tillitis-iceprog 2025-05-22 15:06:39 +02:00
Mikael Ågren
7b1c1e5076
testapp: Update to 24 MHz clock 2025-05-22 09:31:54 +02:00
Michael Cardell Widerkrantz
1fec28ff0d
doc: Complete copyright and licenses
- Point out licensing terms in docs.
- Add missing SPDX tags
- Update the SPDX checker to check all the files we want to check.
- Include spdx-ensure in CI.
2025-05-22 09:31:54 +02:00
Michael Cardell Widerkrantz
8f9c706b9e
doc: Correct the GPL file
Import file

https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt

verbatim since it clearly says in the license that we are now allowed
to change it. I think it might have been a cut and paste from

https://www.gnu.org/licenses/old-licenses/gpl-2.0.html

before?
2025-05-22 09:31:54 +02:00
Mikael Ågren
07e487733b
build: Check app code formatting from application_fpga/Makefile 2025-05-22 09:31:54 +02:00
Michael Cardell Widerkrantz
ba17a2b29e
build: Use only one Makefile for apps
- Use one common Makefile for all test device apps.
- Use a single copy of syscall.[Sh].
- Update docs for building.
2025-05-22 09:31:50 +02:00
Michael Cardell Widerkrantz
6e3034c3ce
build: Move .clang-format to top level 2025-05-21 09:44:17 +02:00
Michael Cardell Widerkrantz
e302910f4d
Remove superfluous file __init__.py 2025-05-20 17:41:18 +02:00
Michael Cardell Widerkrantz
13641cb18b
build: Move test applications and the defaultapp
Instead of having the test apps under fw we create a new directory for
them.
2025-05-20 17:37:58 +02:00
Michael Cardell Widerkrantz
69940d2c64
doc: Link to firmware docs from TKey hardware design 2025-05-20 17:28:01 +02:00
Michael Cardell Widerkrantz
4ec58ce04c
tools: Prune and document tools
Add a tools/README.md.

Remove:

- create_flash_image.py: role now overtaken by tkeyimage which does
  more.
- reset-tk1: Leftover from when production_test was removed.

Rename:

- makehex.py: Moved up one level.
2025-05-20 17:12:46 +02:00
Michael Cardell Widerkrantz
a1f37d17c9
tool: Rename partition_table to tkeyimage 2025-05-20 13:50:55 +02:00
Michael Cardell Widerkrantz
fab126b695
tool: Add docs to partition_table
Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-05-20 13:50:55 +02:00
Michael Cardell Widerkrantz
9a17aa6bdb
tool: Add SPDX tag to partition_table 2025-05-20 13:50:55 +02:00
Michael Cardell Widerkrantz
0d6e1d9ba5
fw: Add debug print when reading partition table fails 2025-05-20 13:50:55 +02:00
Michael Cardell Widerkrantz
ea29843037
tool: Make partition_table able to produce flash file
Usage:

  ./partition_table -o flash.bin -f -app0 path/to/app

Will produce a flash.bin that can be used for qemu.

- Adjust the size of the partition table.
- Refactor and rename genPartitionFile().
2025-05-20 13:50:51 +02:00
Mikael Ågren
6afdc114b8
Update binary hashes for bitstream 2025-05-20 11:59:44 +02:00
Mikael Ågren
2556f61f5a
fpga: Bump tk1 core version to 6 2025-05-20 11:27:07 +02:00
Mikael Ågren
b144cdfbdb
fpga: Use Castor specific VID/PID in UDI
Allows an app to determine which type of device it is running on.

- Reserve vendor ID 0x7357 for people using Unlocked.
- Use Castor product ID.
- Serial number is just nonsense, as before.
2025-05-20 11:25:54 +02:00
Michael Cardell Widerkrantz
8965fea947
Reset USB controller endpoints when starting
When starting, reset the USB controller to only enable the USB CDC
endpoint and the internal command channel. If the app resets firmware,
but had differend endpoints enabled, we want to go back to a known
state.
2025-05-16 17:09:13 +02:00
Mikael Ågren
daa7807c0f
Update binary hashes for bitstream & firmware 2025-05-15 16:15:14 +02:00
Mikael Ågren
53bc2d5fa0
fw: Update flash_write_data() to handle sizes larger than 4096 bytes 2025-05-15 16:13:30 +02:00
Mikael Ågren
5a9b77806f
fw: Return 0 on sys_alloc success, -1 on error
It is left to the app to keep track of whether it has had access to the
allocated area before.
2025-05-15 16:13:30 +02:00
Mikael Ågren
887883c8db
fw: Allow last storage area sector to be erased 2025-05-15 16:13:29 +02:00
Mikael Ågren
2dce9828ea
Update binary hashes for bitstream & firmware 2025-05-15 14:14:52 +02:00
Mikael Ågren
a2b77ec348
fw: Return reset() return value in TK1_SYSCALL_RESET 2025-05-15 14:14:39 +02:00
Mikael Ågren
9a3b4b9dca
fw: Use sizeof(resetinfo->app_digest) instead of hardcoded value 2025-05-15 14:14:38 +02:00
Michael Cardell Widerkrantz
48108cb3a2
fw: Build qemu_firmware with different linker script
The qemu_firmware is too large for the real hardware's 8k of ROM. The
emulator, however, has lots of ROM. Use a different linker script for
to reflect this.
2025-05-15 14:03:04 +02:00
Michael Cardell Widerkrantz
e935195846
fw: Add syscall TK1_SYSCALL_GET_APP_DATA
Add a new syscall to enable an app to get the data left for it by the
previous app in chain.

- Change testloadapp to leave some data for the next app to read.
- Call system call with:

  uint8_t next_app_data[RESET_DATA_SIZE];

  syscall(TK1_SYSCALL_GET_APP_DATA, (uint32_t)next_app_data, 0, 0);
2025-05-15 14:03:04 +02:00
Jonas Thörnblad
14e4cd09c9
ch552: Fix FIDO data copy
Fix potential out of bounds write.
2025-05-07 10:39:10 +02:00
Jonas Thörnblad
ec9ef31140
doc: Fix endpoint info 2025-05-07 10:22:29 +02:00
Michael Cardell Widerkrantz
6745c56851
Update binary hashes for bitstream & firmware 2025-05-06 17:52:14 +02:00
Michael Cardell Widerkrantz
fea9df790d
fw/docs: Correct documentation
Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-05-06 17:52:10 +02:00
Michael Cardell Widerkrantz
8cf2cd08b7
fw/defaultapp: Introduce simple default app
To retain the default behaviour from Bellatrix, we introduce a simple
default app. If used on flash app slot 0 we get the same behaviour as
in Bellatrix, that is, waiting for an app from the client.
2025-05-06 17:52:09 +02:00
Michael Cardell Widerkrantz
d83d659284
fw: Remove use of timer in flash operations
Since we want to keep the user of the timer to the device apps, remove
the use of the timer for implementing a delay when writing to flash.
Let's try without any delay what so ever, just busylooping the query
to the chip.
2025-05-06 17:52:09 +02:00
Michael Cardell Widerkrantz
4f4de4a07d
fw: Harmonize comment style 2025-05-06 17:52:09 +02:00
Michael Cardell Widerkrantz
f373ad3f68
fw: Introduce reset()
- New function reset.c:reset(). Move code from syscall handler switch
  to this function.

- Rename resetinfo.h to reset.h.
2025-05-06 17:52:05 +02:00
Michael Cardell Widerkrantz
9d1bbffbaa
fw: Remove unneeded variable
Instead of assigning error to a variable, just include the function
returning the error in the if case.
2025-04-29 22:00:54 +02:00
Michael Cardell Widerkrantz
0692dddbae
fw: Simplify error return codes
Since callees doesn't differentiate between different errors, we have
no list of what different error codes mean, just return -1 on all
errors.
2025-04-29 22:00:51 +02:00
Mikael Ågren
15a350da1e
fw: Set LED colors
- Set LED color to white when firmware has initialized
- Set LED color to black when changing state to loading
- Set LED color to blue when starting testloadapp
- Update mgmt app allowed digest since testloadapp changed
2025-04-29 21:58:50 +02:00
Mikael Ågren
edbcdb111f
fw: Update default partition table 2025-04-29 21:58:50 +02:00
Michael Cardell Widerkrantz
3e8ff9671c
fw/tools: Change partition checksum to vanilla BLAKE2s
Instead of using 16 byte BLAKE2s with a dummy key, use plain vanilla
unkeyed 32 byte BLAKE2s for partition checksum.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-04-29 21:58:50 +02:00
Michael Cardell Widerkrantz
66ea8df1d9
fw: Rename partition digest to checksum
- Rename functions, defines, et c to indicate that it's a checksum
  over the partition, not necessarily a cryptographic hash digest even
  though we use a version of BLAKE2s.

- Add comments describing where the checksum is stored and what it is
  used for.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-04-29 21:54:06 +02:00
Michael Cardell Widerkrantz
106a7a5613
fw: Check flash app length to be within limits
Complain if the pre-loaded app on flash is larger than app RAM.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-04-29 21:53:36 +02:00
Michael Cardell Widerkrantz
49d5a26a77
fw: Check syscall arg pointers to be in app RAM
When we pass pointers in system calls these pointers should point to
app RAM, not any other parts of the memory map, and especially not to
memory like FW_RAM that is only available in in a higher privilege
mode.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-04-29 21:53:24 +02:00
Michael Cardell Widerkrantz
632b6d8fc7
fw: Limit flash offsets to be within sane limits
Limit flash offsets passed to syscalls. Be sure to check the limits
before doing any form of calculation with the passed values.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-04-28 15:21:10 +02:00
Mikael Ågren
506b4c8269
doc: Add ERASE_DATA syscall 2025-04-24 16:03:21 +02:00
Mikael Ågren
9c1bb53d7a
fw: Add ERASE_DATA syscall
Erase one or more flash sectors in app storage areas
2025-04-24 16:03:20 +02:00
Michael Cardell Widerkrantz
a9d3dd7242
testapp: Use tkey-libs crt0 and linker script 2025-04-24 16:03:05 +02:00
Michael Cardell Widerkrantz
3be9e8ab19
doc: Update release notes with filesystem things 2025-04-24 16:03:05 +02:00
Michael Cardell Widerkrantz
d7ddae42d0
doc: Update firmware README
- Describe all the new functionality.
- Revise text.
2025-04-24 16:03:05 +02:00
Mikael Ågren
18773cdcf2
fw: Use globbing for FMTFILES 2025-04-24 16:03:04 +02:00
Michael Cardell Widerkrantz
25f3300964
fw: Change splint config
- Now uses at least some of the standard libraries like stdlib.h,
  stddef.h, et cetera.

- Include LIBDIR headers.

- Disregard some warnings globally.
2025-04-24 16:03:04 +02:00
Michael Cardell Widerkrantz
c1902c0955
fw: Rename FIRMWARE_SOURCES, use globbing
The symbol is only used for the check targets (with clangd and splint)
and doesn't include all the source files in the firmware. Let's just
use globbing instead.
2025-04-24 16:03:04 +02:00
Mikael Ågren
528f997681
tool: Add script to load pre-loaded app into flash 2025-04-24 16:03:03 +02:00
Michael Cardell Widerkrantz
73ea180b2a
tool: Add default_partition.bin
Add default partition table

Partition table built with `./partition_table/partition_table -o
default_partition.bin --app0 ../fw/testloadapp/testloadapp.bin`
2025-04-24 16:03:03 +02:00
Michael Cardell Widerkrantz
6324da2c90
tool: Introduce b2s tool to help compute BLAKE2s digests 2025-04-24 16:03:03 +02:00
Mikael Ågren
7511e98abe
tool: Add tool to inspect and create partition table binaries 2025-04-24 16:03:02 +02:00
Mikael Ågren
8c091d9719
tool: Add tool to create a flash image containing a preloaded app at slot 0 2025-04-24 16:03:02 +02:00
Michael Cardell Widerkrantz
ce97682758
testloadapp: Add app for testing preloaded app functionality
Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-04-24 16:03:02 +02:00
Jonas Thörnblad
e37985938d
reset_test: Add resetinfo testapp
Co-authored-by: Mikael Ågren <mikael@tillitis.se>
Co-authored-by: Michael Cardell Widerkrantz <mc@tillitis.se>
2025-04-24 16:03:01 +02:00
Mikael Ågren
c5c6230664
fw: Replace custom picorv32 instructions when building for qemu 2025-04-24 16:03:01 +02:00
Mikael Ågren
49c06d78d1
testapp: Call storage syscalls
Calls
- TK1_SYSCALL_ALLOC_AREA
- TK1_SYSCALL_WRITE_DATA
- TK1_SYSCALL_READ_DATA
- TK1_SYSCALL_DEALLOC_AREA
2025-04-24 16:03:01 +02:00
Michael Cardell Widerkrantz
2c1c05f180
fw: Add pre loaded flash app and flash data storage
- Add per app flash storage
  - Adds four data areas. An app can allocate an area. Once allocated
    the area is tied to the CDI of the app and can only be
    read/written/deallocated by the same app.
- Add two pre loaded app slots to flash
  - Load an app from the first slot at boot. The app digest must match a
    specific digest specified in firmware.
  - Optionally load an app from the second slot
- Add a resetinfo area in FW_RAM which is used to signal an app's intent
  of resetting the system and, optionally, pass data to firmware or the
  next app in a bootchain.

Co-authored-by: Jonas Thörnblad <jonas@tillitis.se>
Co-authored-by: Mikael Ågren <mikael@tillitis.se>
Co-authored-by: Daniel Jobson <jobson@tillitis.se>
2025-04-24 16:02:34 +02:00
Michael Cardell Widerkrantz
4841b1b127
fw: Use BLAKE2s functions from tkey-libs
Instead of using the firmware's own copy of BLAKE2s functions, use the
functions from tkey-libs.
2025-04-24 09:10:55 +02:00
Michael Cardell Widerkrantz
1be5140850
tkey-libs: Optimize for size
Optimize tkey-libs for size to fit firmware in ROM
2025-04-24 09:10:55 +02:00
Mikael Ågren
353d7e9f50
tkey-libs: Import tag fw-4 of tkey-libs
- Use tag fw-4 from https://github.com/tillitis/tkey-libs/
2025-04-23 15:13:28 +02:00
Jonas Thörnblad
f75620720f
ch552: Clean up debugging of USB stack 2025-04-17 10:27:57 +02:00
Jonas Thörnblad
fb1269b06e
ch552: Fix various USB stack things, add check for IO_CH552 command range.
- Move handling of returning data from USB_GET_DESCRIPTOR request.
- Fix correct size of ActiveCfgDesc descriptor.
- Add missing check for limiting total length in USB_CDC_REQ_TYPE_GET_LINE_CODING.
- Add missing break in DeviceInterrupt to follow coding style.
- Check command range for IO_CH552.
- Add some comments.
2025-04-17 10:27:57 +02:00
Jonas Thörnblad
770acc9b38
ch552: Add CCID (Smart Card) support 2025-04-17 10:27:56 +02:00
161 changed files with 3341 additions and 2384 deletions

View file

@ -13,7 +13,7 @@ jobs:
check-formatting:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:5rc1
image: ghcr.io/tillitis/tkey-builder:5rc2
steps:
- name: checkout
uses: actions/checkout@v4
@ -34,7 +34,7 @@ jobs:
check-firmware:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:5rc1
image: ghcr.io/tillitis/tkey-builder:5rc2
steps:
- name: checkout
uses: actions/checkout@v4
@ -47,19 +47,19 @@ jobs:
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: compile firmware and testfw
working-directory: hw/application_fpga
run: make firmware.bin testfw.bin
- name: run static analysis on firmware C code
working-directory: hw/application_fpga
run: |
make check
- name: compile firmware and testfw
working-directory: hw/application_fpga
run: make firmware.bin testfw.bin
check-verilog:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:5rc1
image: ghcr.io/tillitis/tkey-builder:5rc2
steps:
- name: checkout
uses: actions/checkout@v4
@ -79,7 +79,7 @@ jobs:
build-usb-firmware:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:5rc1
image: ghcr.io/tillitis/tkey-builder:5rc2
steps:
- name: checkout
uses: actions/checkout@v4
@ -101,7 +101,7 @@ jobs:
commit_sha: ${{ github.sha }}
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:5rc1
image: ghcr.io/tillitis/tkey-builder:5rc2
steps:
- name: checkout
uses: actions/checkout@v4
@ -130,7 +130,7 @@ jobs:
needs: build-bitstream
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:5rc1
image: ghcr.io/tillitis/tkey-builder:5rc2
steps:
- name: Checkout
uses: actions/checkout@v4
@ -150,6 +150,13 @@ jobs:
run: make check-binary-hashes
# TODO? first deal with hw/boards/ and hw/production_test/
# - name: check for SPDX tags
# run: ./LICENSES/spdx-ensure
reuse-compliance-check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v4
with:
args: lint

7
.gitignore vendored
View file

@ -28,11 +28,8 @@
/testbench_verilator*
/check.smt2
/check.vcd
/hw/application_fpga/tkey-libs/libcommon.a
/hw/application_fpga/tkey-libs/libcrt0.a
/hw/application_fpga/tkey-libs/libmonocypher.a
/hw/application_fpga/tkey-libs/libblake2s.a
/hw/application_fpga/tools/partition_table/partition_table
/hw/application_fpga/tkey-libs/*.a
/hw/application_fpga/tools/tkeyimage/tkeyimage
/hw/application_fpga/tools/b2s/b2s
synth.json
synth.txt

24
LICENSES/BSD-2-Clause.txt Normal file
View file

@ -0,0 +1,24 @@
Copyright 2022 Tillitis AB <tillitis.se>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

121
LICENSES/CC0-1.0.txt Normal file
View file

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View file

@ -1,21 +0,0 @@
# Tillitis TKey Licensing
## Main license
Unless otherwise noted, the project sources are licensed under the
terms and conditions of the "GNU General Public License v2.0 only".
The `LICENSES/` directory contains copies of the license texts used by
the sources included in the project source tree.
## SPDX
The project uses single-line references to Unique License Identifiers
as defined by the Linux Foundation's [SPDX project](https://spdx.org/).
The line in each individual source file identifies the license
applicable to that file.
The current set of valid, predefined SPDX identifiers can be found on
the SPDX License List at:
https://spdx.org/licenses/

View file

@ -1,23 +0,0 @@
Copyright (c) <year>, <owner>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,116 +0,0 @@
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.
For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

View file

@ -1,245 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and
change it. By contrast, the GNU General Public License is intended to guarantee your
freedom to share and change free software--to make sure the software is free for all
its users. This General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to using it.
(Some other Free Software Foundation software is covered by the GNU Lesser General
Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General
Public Licenses are designed to make sure that you have the freedom to distribute
copies of free software (and charge for this service if you wish), that you receive
source code or can get it if you want it, that you can change the software or use
pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you
these rights or to ask you to surrender the rights. These restrictions translate to
certain responsibilities for you if you distribute copies of the software, or if you
modify it.
For example, if you distribute copies of such a program, whether gratis or for a
fee, you must give the recipients all the rights that you have. You must make sure
that they, too, receive or can get the source code. And you must show them these
terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you
this license which gives you legal permission to copy, distribute and/or modify the
software.
Also, for each author's protection and ours, we want to make certain that everyone
understands that there is no warranty for this free software. If the software is
modified by someone else and passed on, we want its recipients to know that what
they have is not the original, so that any problems introduced by others will not
reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to
avoid the danger that redistributors of a free program will individually obtain
patent licenses, in effect making the program proprietary. To prevent this, we have
made it clear that any patent must be licensed for everyone's free use or not
licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed
by the copyright holder saying it may be distributed under the terms of this General
Public License. The "Program", below, refers to any such program or work, and a
"work based on the Program" means either the Program or any derivative work under
copyright law: that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another language.
(Hereinafter, translation is included without limitation in the term
"modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this
License; they are outside its scope. The act of running the Program is not
restricted, and the output from the Program is covered only if its contents
constitute a work based on the Program (independent of having been made by running
the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and appropriately publish
on each copy an appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any warranty; and
give any other recipients of the Program a copy of this License along with the
Program.
You may charge a fee for the physical act of transferring a copy, and you may at
your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus
forming a work based on the Program, and copy and distribute such modifications or
work under the terms of Section 1 above, provided that you also meet all of these
conditions:
a) You must cause the modified files to carry prominent notices stating that you
changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in
part contains or is derived from the Program or any part thereof, to be licensed
as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you
must cause it, when started running for such interactive use in the most
ordinary way, to print or display an announcement including an appropriate
copyright notice and a notice that there is no warranty (or else, saying that
you provide a warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this License. (Exception:
if the Program itself is interactive but does not normally print such an
announcement, your work based on the Program is not required to print an
announcement.)
These requirements apply to the modified work as a whole. If identifiable sections
of that work are not derived from the Program, and can be reasonably considered
independent and separate works in themselves, then this License, and its terms, do
not apply to those sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based on the
Program, the distribution of the whole must be on the terms of this License, whose
permissions for other licensees extend to the entire whole, and thus to each and
every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to
work written entirely by you; rather, the intent is to exercise the right to control
the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the
Program (or with a work based on the Program) on a volume of a storage or
distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2)
in object code or executable form under the terms of Sections 1 and 2 above provided
that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code,
which must be distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give
any third party, for a charge no more than your cost of physically performing
source distribution, a complete machine-readable copy of the corresponding
source code, to be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute
corresponding source code. (This alternative is allowed only for noncommercial
distribution and only if you received the program in object code or executable
form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making
modifications to it. For an executable work, complete source code means all the
source code for all modules it contains, plus any associated interface definition
files, plus the scripts used to control compilation and installation of the
executable. However, as a special exception, the source code distributed need not
include anything that is normally distributed (in either source or binary form) with
the major components (compiler, kernel, and so on) of the operating system on which
the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from
a designated place, then offering equivalent access to copy the source code from the
same place counts as distribution of the source code, even though third parties are
not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as
expressly provided under this License. Any attempt otherwise to copy, modify,
sublicense or distribute the Program is void, and will automatically terminate your
rights under this License. However, parties who have received copies, or rights,
from you under this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it.
However, nothing else grants you permission to modify or distribute the Program or
its derivative works. These actions are prohibited by law if you do not accept this
License. Therefore, by modifying or distributing the Program (or any work based on
the Program), you indicate your acceptance of this License to do so, and all its
terms and conditions for copying, distributing or modifying the Program or works
based on it.
6. Each time you redistribute the Program (or any work based on the Program), the
recipient automatically receives a license from the original licensor to copy,
distribute or modify the Program subject to these terms and conditions. You may not
impose any further restrictions on the recipients' exercise of the rights granted
herein. You are not responsible for enforcing compliance by third parties to this
License.
7. If, as a consequence of a court judgment or allegation of patent infringement or
for any other reason (not limited to patent issues), conditions are imposed on you
(whether by court order, agreement or otherwise) that contradict the conditions of
this License, they do not excuse you from the conditions of this License. If you
cannot distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may not
distribute the Program at all. For example, if a patent license would not permit
royalty-free redistribution of the Program by all those who receive copies directly
or indirectly through you, then the only way you could satisfy both it and this
License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular
circumstance, the balance of the section is intended to apply and the section as a
whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other
property right claims or to contest validity of any such claims; this section has
the sole purpose of protecting the integrity of the free software distribution
system, which is implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed through that system
in reliance on consistent application of that system; it is up to the author/donor
to decide if he or she is willing to distribute software through any other system
and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries
either by patents or by copyrighted interfaces, the original copyright holder who
places the Program under this License may add an explicit geographical distribution
limitation excluding those countries, so that distribution is permitted only in or
among countries not thus excluded. In such case, this License incorporates the
limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the
General Public License from time to time. Such new versions will be similar in
spirit to the present version, but may differ in detail to address new problems or
concerns.
Each version is given a distinguishing version number. If the Program specifies a
version number of this License which applies to it and "any later version", you have
the option of following the terms and conditions either of that version or of any
later version published by the Free Software Foundation. If the Program does not
specify a version number of this License, you may choose any version ever published
by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose
distribution conditions are different, write to the author to ask for permission.
For software which is copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our decision will be
guided by the two goals of preserving the free status of all derivatives of our free
software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE
PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN
WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM
AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE
OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

View file

@ -1,107 +0,0 @@
#!/bin/bash
set -eu
# Check for the SPDX tag in all files in the repo. Exit with a non-zero code if
# some is missing. The missingok arrays below contain files and directories
# with files where the the tag is not required.
cd "${0%/*}"
cd ..
tag="SPDX-License-Identifier:"
missingok_dirs=(
.github/workflows/
LICENSES/
doc/
hw/application_fpga/core/picorv32/
hw/application_fpga/core/uart/
hw/application_fpga/fw/tk1/blake2s/
)
missingok_files=(
.editorconfig
.gitattributes
.gitignore
README.md
contrib/99-tillitis.rules
contrib/Dockerfile
contrib/Makefile
dco.md
hw/application_fpga/application_fpga.bin.sha256
hw/application_fpga/config.vlt
hw/application_fpga/core/timer/README.md
hw/application_fpga/core/tk1/README.md
hw/application_fpga/core/touch_sense/README.md
hw/application_fpga/core/trng/README.md
hw/application_fpga/core/uds/README.txt
hw/application_fpga/data/udi.hex
hw/application_fpga/data/uds.hex
hw/application_fpga/firmware.bin.sha512
hw/application_fpga/fw/.clang-format
hw/application_fpga/fw/testfw/Makefile
hw/application_fpga/fw/tk1/Makefile
hw/application_fpga/tools/makehex/makehex.py
hw/application_fpga/tools/reset-tk1
hw/application_fpga/tools/tpt/README.md
)
is_missingok() {
item="$1"
# ok for empty files
[[ -f "$item" ]] && [[ ! -s "$item" ]] && return 0
for fileok in "${missingok_files[@]}"; do
[[ "$item" = "$fileok" ]] && return 0
done
for dirok in "${missingok_dirs[@]}"; do
[[ "$item" =~ ^$dirok ]] && return 0
done
return 1
}
printf "* Checking for SPDX tags in %s\n" "$PWD"
mapfile -t repofiles < <(git ls-files || true)
if [[ -z "${repofiles[*]}" ]]; then
printf "* No files in the repo?!\n"
exit 1
fi
failed=0
printed=0
for fileok in "${missingok_files[@]}"; do
[[ -f "$fileok" ]] && continue
if (( !printed )); then
printf "* Some files in missingok_files are themselves missing:\n"
printed=1
failed=1
fi
printf "%s\n" "$fileok"
done
printed=0
for dirok in "${missingok_dirs[@]}"; do
[[ -d "$dirok" ]] && continue
if (( !printed )); then
printf "* Some dirs in missingok_dirs are themselves missing:\n"
printed=1
failed=1
fi
printf "%s\n" "$dirok"
done
printed=0
for file in "${repofiles[@]}"; do
is_missingok "$file" && continue
if ! grep -q "$tag" "$file"; then
if (( !printed )); then
printf "* Files missing the SPDX tag:\n"
printed=1
failed=1
fi
printf "%s\n" "$file"
fi
done
exit "$failed"

121
README.md
View file

@ -40,8 +40,49 @@ software and hardware should be.
## Licensing
See [LICENSES](./LICENSES/README.md) for more information about
the projects' licenses.
Unless otherwise noted, the project sources are copyright Tillitis AB,
but you can redistribute it and/or modify it under the terms of the
BSD-2-Clause license.
Until Oct 29, 2025, the license was GPL-2.0 Only.
Each imported project is typically kept in its own directory with its
own LICENSE file.
### SPDX
The project uses single-line references to Unique License Identifiers
as defined by the Linux Foundation's [SPDX project](https://spdx.org/).
The line in each individual source file identifies the license
applicable to that file.
The current set of valid, predefined SPDX identifiers can be found on
the SPDX License List at:
https://spdx.org/licenses/
We attempt to follow the [REUSE
specification](https://reuse.software/).
### Notable imported projects
- ch552 firmware: `hw/usb_interface/ch552_fw/`
Originally by WCH under MIT. Much changed by Tillitis.
- picorv32: `hw/application_fpga/core/picorv32`
From https://github.com/YosysHQ/picorv32
ISC.
- PicoRV32 custom ops: `hw/application_fpga/fw/tk1/picorv32/`
CC-1.
- tkey-libs: `hw/application_fpga/tkey-libs/`
BSD2. From https://github.com/tillitis/tkey-libs
## Repositories
@ -77,26 +118,86 @@ https://github.com/tillitis/tkey-libs
but keep our own copy of it in the repo. See below.
## Building
## Building & flashing
Building is probably easiest using make and Podman. Do this to see all
targets:
These instructions assume you're using a Linux distribution. Most of
them also assume you're using our OCI image
[tkey-builder](https://ghcr.io/tillitis/tkey-builder). If you want to
run native tools, look in `contrib/Dockerfile` and
`contrib/buildtools.sh` for the tools and versions to use.
### FPGA
You need a [TKey
Unlocked](https://shop.tillitis.se/products/tkey-not-provisioned), a
[the TP1 TKey Programmer
board](https://shop.tillitis.se/products/tkey-dev-kit), and probably a
[Blinkinlabs CH55x Reset
Controller](https://shop-nl.blinkinlabs.com/products/ch55x-reset-controller)
to use this on real hardware.
Building is probably easiest using make and Podman.
To build everything and then flash the resulting bitstream with the
defaultapp in app slot 0 and the partition table copies in one go,
place the TKey Unlocked in the TP1, then do:
```
cd contrib
make flash
```
This uses the make target `prog_flash` in
`hw/application_fpga/Makefile` behind the scenes, but mounts your TP1
device into the container.
If you want to change the default app the TKey uses, change
`DEFAULT_APP` in the `hw/application_fpga/Makefile`.
To see all container targets:
```
cd contrib
make
```
Build the entire FPGA bitstream, which includes the firmware, using
Podman:
See the [Tillitis Developer Handbook](https://dev.tillitis.se) for
more.
### USB Controller
The TKey uses a WCH CH552 chip as a USB controller. It has its own
firmware.
Build:
```
cd contrib
make run-make
make run
cd hw/usb_interface/ch552_fw
make
```
See the [Tillitis Developer Handbook](https://dev.tillitis.se) for
more.
To flash the controller with new firmware you need hardware like the
[Blinkinlabs CH55x Reset
Controller](https://shop-nl.blinkinlabs.com/products/ch55x-reset-controller)
and a USB-A to USB-C converter.
[Reset Controller source](https://github.com/Blinkinlabs/ch55x_programmer).
You also need [chprog](https://github.com/ole00/chprog).
The bootloader identifies itself as USB VID 4348, PID 55e0. To be able
to access it and run `chprog` without root you need to allow your user
to access it. Place `contrib/99-tillitis.rules` in `/etc/udev/rules.d`
and run `udevadm control --reload`. Now you can add your user to the
`dialout` group and access it.
1. Connect the Reset Controller to your computer through "DUT\_IN"/"PC".
2. Connect the TKey to "DUT\_OUT"/"DUT".
3. Press the "Bootloader" button.
4. Run `make flash_patched` in `hw/usb_interface/ch552_fw` outside of
a container.
## Updating and working with tkey-libs

62
REUSE.toml Normal file
View file

@ -0,0 +1,62 @@
# SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
version = 1
[[annotations]]
path = ".github/workflows/*"
SPDX-FileCopyrightText = "2022 Tillitis AB <tillitis.se>"
SPDX-License-Identifier = "BSD-2-Clause"
[[annotations]]
path = [
".clang-format",
".editorconfig",
".gitattributes",
".gitignore",
"README.md",
"contrib/99-tillitis.rules",
"contrib/Dockerfile",
"contrib/verible.sha512",
"doc/images/application_fpga_block_diagram.png",
"doc/images/tkey-open-lid.png",
"doc/release_notes.md",
"doc/threat_model/threat_model.md",
"hw/application_fpga/README.md",
"hw/application_fpga/application_fpga.bin.sha256",
"hw/application_fpga/apps/README.md",
"hw/application_fpga/config.vlt",
"hw/application_fpga/core/clk_reset_gen/README.md",
"hw/application_fpga/core/fw_ram/README.md",
"hw/application_fpga/core/picorv32/README.md",
"hw/application_fpga/core/ram/README.md",
"hw/application_fpga/core/rom/README.md",
"hw/application_fpga/core/timer/README.md",
"hw/application_fpga/core/tk1/README.md",
"hw/application_fpga/core/tk1/tb/README.txt",
"hw/application_fpga/core/tk1/tb/udi.hex",
"hw/application_fpga/core/touch_sense/README.md",
"hw/application_fpga/core/trng/README.md",
"hw/application_fpga/core/uart/README.md",
"hw/application_fpga/core/uds/README.md",
"hw/application_fpga/data/udi.hex",
"hw/application_fpga/data/uds.hex",
"hw/application_fpga/firmware.bin.sha512",
"hw/application_fpga/fw/README.md",
"hw/application_fpga/fw/tk1/picorv32/README.md",
"hw/application_fpga/tools/README.md",
"hw/application_fpga/tools/b2s/README.md",
"hw/application_fpga/tools/b2s/go.mod",
"hw/application_fpga/tools/b2s/go.sum",
"hw/application_fpga/tools/tkeyimage/README.md",
"hw/application_fpga/tools/tkeyimage/go.mod",
"hw/application_fpga/tools/tkeyimage/go.sum",
"hw/application_fpga/tools/tpt/README.md",
]
SPDX-FileCopyrightText = "2022 Tillitis AB <tillitis.se>"
SPDX-License-Identifier = "BSD-2-Clause"
[[annotations]]
path = "hw/application_fpga/core/picorv32/rtl/picorv32.v"
SPDX-License-Identifier = "ISC"

View file

@ -18,6 +18,7 @@ RUN apt-get -qq update -y \
gawk \
gcc \
git \
golang-1.23 \
gperf \
graphviz \
help2man \
@ -68,3 +69,4 @@ RUN /buildtools.sh
FROM base
LABEL org.opencontainers.image.description="Toolchain for building TKey FPGA bitstream"
COPY --from=toolsbuilder /usr/local/ /usr/local
ENV PATH="$PATH:/usr/lib/go-1.23/bin"

View file

@ -1,25 +1,27 @@
# Copyright (C) 2024 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
# image produced by build-image targets
BUILDIMAGE=tkey-builder-local
# default image used when running a container
IMAGE=ghcr.io/tillitis/tkey-builder:5rc1
IMAGE=ghcr.io/tillitis/tkey-builder:5rc2
all:
@echo "Targets:"
@echo "run Run a shell using image '$(IMAGE)' (Podman)"
@echo "run-make Build the FPGA bitstream using image '$(IMAGE)' (Podman)"
@echo "run-tb Run all the testbenches using image '$(IMAGE)' (Podman)"
@echo "run-make-no-clean Like run-make but without cleaning first, useful for iterative firmware dev"
@echo "run-make-clean_fw Like run-make but cleans only firmware"
@echo "flash Program the SPI flash on the TKey - needs an existing bitstream"
@echo "pull Pull down the image '$(IMAGE)' (Podman)"
@echo "build-image Build a toolchain image named '$(BUILDIMAGE)' (Podman)"
@echo " A newly built image can be used like: make IMAGE=$(BUILDIMAGE) run"
@echo "docker-run Run a shell using image '$(IMAGE)' (Docker)"
@echo "docker-build-image Build a toolchain image named '$(BUILDIMAGE)' (Docker)"
@echo "run Run a shell using image '$(IMAGE)' (Podman)"
@echo "run-make Build the FPGA bitstream using image '$(IMAGE)' (Podman)"
@echo "run-make-ch552 Build the CH552 firmware using image '$(IMAGE)' (Podman)"
@echo "run-tb Run all the testbenches using image '$(IMAGE)' (Podman)"
@echo "run-make-no-clean Like run-make but without cleaning first, useful for iterative firmware dev"
@echo "run-make-ch552-no-clean Like run-make-ch552 but without cleaning first, useful for iterative firmware dev"
@echo "run-make-clean_fw Like run-make but cleans only firmware"
@echo "flash Build bitstream and defaultapp.bin then program them and the partition table onto the TKey SPI flash"
@echo "pull Pull down the image '$(IMAGE)' (Podman)"
@echo "build-image Build a toolchain image named '$(BUILDIMAGE)' (Podman)"
@echo " A newly built image can be used like: make IMAGE=$(BUILDIMAGE) run"
@echo "docker-run Run a shell using image '$(IMAGE)' (Docker)"
@echo "docker-build-image Build a toolchain image named '$(BUILDIMAGE)' (Docker)"
run:
podman run --rm --mount type=bind,source="`pwd`/../",target=/build -w /build -it \
@ -33,6 +35,10 @@ run-make:
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
$(IMAGE) make clean application_fpga.bin
run-make-ch552:
podman run --rm --mount type=bind,source="`pwd`/../hw/usb_interface/ch552_fw",target=/build -w /build -it \
$(IMAGE) make clean usb_device.bin
run-tb:
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
$(IMAGE) make clean_tb tb
@ -45,6 +51,10 @@ run-make-no-clean:
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
$(IMAGE) make application_fpga.bin
run-make-ch552-no-clean:
podman run --rm --mount type=bind,source="`pwd`/../hw/usb_interface/ch552_fw",target=/build -w /build -it \
$(IMAGE) make usb_device.bin
run-make-clean_fw:
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
$(IMAGE) make clean_fw application_fpga.bin
@ -54,7 +64,7 @@ flash:
--device /dev/bus/usb/$(lsusb | grep -m 1 1209:8886 | awk '{ printf "%s/%s", $2, substr($4,1,3) }') \
--mount type=bind,source="`pwd`/../hw/application_fpga",target=/build \
-w /build \
-it $(IMAGE) tillitis-iceprog /build/application_fpga.bin
-it $(IMAGE) make prog_flash
pull:

View file

@ -1,7 +1,7 @@
#! /bin/sh -e
# Copyright (C) 2025 Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
## Build the specific versions of the tools we need to build the TKey
## FPGA bitstream and apps.

View file

@ -4,8 +4,12 @@ Descriptions of the tagged TKey releases.
## Upcoming release: Castor
Overview of changes since TK TK1-24.03 for the Castor milestone so
far.
Overview of changes since [TK1-24.03
Bellatrix](https://github.com/tillitis/tillitis-key1/releases/tag/TK1-24.03)
for the Castor milestone so far.
Main branch in the repository contains Castor design and specifically
the tag `TK1-Castor-alpha-1` reflects the upcoming release.
**Note well**: BREAKING CHANGE! Older device apps WILL NOT WORK.
@ -14,38 +18,50 @@ on the PicoRV32 CPU and the CH552 means that device apps that have not
been changed to use the protocol will not have any way to communicate
with the outside world.
### How to test TK1-Castor-alpha
To test this alpha release you will need:
- Tkey Unlocked
- TKey Programmer Board
- CH55x Reset Controller from [Blinkinlabs](https://shop-nl.blinkinlabs.com/products/ch55x-reset-controller)
Read
[here](https://github.com/tillitis/tillitis-key1/blob/main/README.md#building--flashing)
for instructions.
### General
- Split repo:
- tk1, mta1-usb-dev, mta-usb-v1 and mta1-library moves to
https://github.com/tillitis/tk1-pcba
- tk1, mta1-usb-dev, mta-usb-v1 and mta1-library moves to
<https://github.com/tillitis/tk1-pcba>
- tp1, mta1-usb-programmer, mta1-library and KiCad-RP Pico moves to
https://github.com/tillitis/tp1
- tp1, mta1-usb-programmer, mta1-library and KiCad-RP Pico moves to
<https://github.com/tillitis/tp1>
For full change log [see](https://github.com/tillitis/tillitis-key1/compare/TK1-23.03.2...coming-tag)
### FPGA
- Security Monitor memory access checks are now more complete.
- Make Security Monitor memory access checks more complete.
- Add SPI main controller mainly to access the flash chip.
- Add system reset API. Device apps can reset the system and restart
the firmware. The FPGA is not reset.
- Add system reset API. Device apps can reset the FPGA and restart
the firmware.
- Increase clock frequence to 24 MHz.
- Increase UART baudrate to 500,000.
- Fix UART baudrate counter issues noticable at higher baudrates.
- Fix missing clock cycles in timer core.
- Remove the UART runtime configuration API.
- Several clean ups and testbench changes.
- Make Verilator simulation work again.
- Several minor clean ups of design and testbench.
- Add hardware clear to send (CTS) signals for communication between
UART and CH552.
@ -54,19 +70,19 @@ For full change log [see](https://github.com/tillitis/tillitis-key1/compare/TK1-
- Make ROM non-executable in app mode.
- Remove support for access to the firmware blake2s() function from
apps.
- Remove MMIO address for access to the firmware blake2s() function
from apps.
- Automatically leave firmware mode when execution leaves ROM and
remove the now unnecessary APP\_MODE\_CTRL register.
- Add extra protection of UDS: When execution leaves ROM the first
time, UDS is hardware protected from reading, as well as already
existing UDS protection after first read and UDS being unreadable in
app mode.
- Change UDS read protection: When execution leaves ROM the first
time, UDS is hardware protected from reads. The already existing
protection that UDS is protected after the first read is also still
available.
- Introduce interrupt handler for hardware-based privilege raising for
system calls.
- Introduce interrupt handler for hardware-based privilege raising and
automatically privelege lowering for system calls.
### Firmware
@ -74,27 +90,65 @@ For full change log [see](https://github.com/tillitis/tillitis-key1/compare/TK1-
by TRNG.
- Add support for the new USB Mode Protocol to communicate with
different endpoints.
different USB endpoints in the USB controller.
- Support a filesystem on flash.
- Support a filesystem on flash: There's space for two pre-loaded
apps and four storage areas for device apps.
- Add a system call mechanism and system calls: `RESET`, `ALLOC_AREA`,
`DEALLOC_AREA`, `WRITE_DATA`, `READ_DATA`, `PRELOAD_DELETE`,
`PRELOAD_STORE`, `PRELOAD_STORE_FIN`, `PRELOAD_GET_DIGSIG`,
`STATUS`, and `GET_VIDPID`. See [firmware's
README](../hw/application_fpga/fw/README.md) for documentation.
A typical use is that app slot 0 will contain a loader app for
verified boot and app slot 1 contains the app to be verified.
- Automatically start an app in flash app slot 0 after power cycle and
when instructed to by reset intentions.
The automatically started app is trusted by the firmware by
including an app digest in the firmware ROM. This means we extend
the user's trust in the firmware to the first app, but only if it's
measured to the correct digest by the firmware. Anything else is a
hard error which halts the CPU.
- Support chaining of apps through soft resets, including support for
verifying that the next app is the expected one (exact measured
digest the previous app expected), and leaving data for the next app
to use.
- Add a system call mechanism and system calls. See [firmware's
README](../hw/application_fpga/fw/README.md) for documentation, but
its probably easier to use the the syscall wrappers in libsyscall in
[tkey-libs](https://github.com/tillitis/tkey-libs) if you're writing
in C.
- Harmonize with [tkey-libs](https://github.com/tillitis/tkey-libs).
Import tkey-libs to this repo for convenience.
### CH552
- Rewrite test firmware to work with the new leaving ROM-scenario.
Introduce a separate `testapp` for the app mode parts.
### Device apps
Introduce some device apps mostly for testing.
- `reset_test`: Test the different types of soft reset.
- `testapp`: Tests in app mode that used to live in `testfw`.
- `testloadapp`: A simple loader app for management and verification
of a second app.
- `defaultapp`: An app that immediately resets the TKey to load an app
from the client, just like earlier releases.
### CH552 firmware
- Use the new CTS signals for communication over the UART.
- Add support for two HID endpoints.
- Add support for two HID endpoints (security token and our debug
HID).
- Add protocol to communicate with the three different endpoints: CDC,
HID, debug.
- Add support for CCID endpoint.
- Add a protocol to communicate with the different endpoints: CDC,
CCID, FIDO, debug.
- Change USB frame sending from a software timer to instead be
controlled by the USB Controller Protocol.
@ -102,9 +156,15 @@ For full change log [see](https://github.com/tillitis/tillitis-key1/compare/TK1-
Note that to update the CH552 firmware you will need something like
the Blinkinlabs CH55x Reset Controller:
https://shop-nl.blinkinlabs.com/products/ch55x-reset-controller
<https://shop-nl.blinkinlabs.com/products/ch55x-reset-controller>
https://github.com/Blinkinlabs/ch55x_programmer
<https://github.com/Blinkinlabs/ch55x_programmer>
### Tooling
- Add tools to parse and generate partition tables and flash images.
- Add tool to compute a print a BLAKE2s digest, optionally as C code.
### tkey-builder
@ -127,10 +187,13 @@ https://github.com/Blinkinlabs/ch55x_programmer
- libstdc++-arm-none-eabi-newlib
- pico-sdk
TP1 is now in https://github.com/tillitis/tp1
TP1 is now in <https://github.com/tillitis/tp1>
- Remove Go compiler support.
- Introduce buildtools.sh for building upstream tools for inclusion
in the image.
### Docs
- All docs now in READMEs close to the design or code.
@ -155,6 +218,7 @@ the following digest:
```
### FPGA
- Security Monitor now prevents access to RAM outside of the physical
memory. If it detects an access outside of the RAM address space, it
will halt the CPU.
@ -166,6 +230,7 @@ the following digest:
- Complete testbenches and add 9 tests for the FPGA cores.
### Firmware
- Protect zeroisation against compiler optimisation by using
secure_wipe(), fixing a memset() that was removed during
compilation.
@ -180,31 +245,35 @@ the following digest:
- Fix warnings from splint.
### TP1
- New plastic clip o and update of BOM.
- Build TP1 firmware in CI.
### CH552
- Fixed a bug where a byte of data could in some rare circumstances be
dropped, causing a client app to hang.
- General clean-up of code, translated all comments to English.
### TK1
- New injection moulded plastic case
### tkey-builder
- Updated to version 3. Bumping Ubuntu to 23.10, Yosys to 0.36 and
nextpnr to 0.6.
- Updated to version 4. Bumping pico-sdk to 1.5.1, adding clang-tidy
and splint.
### Docs
- Fixing broken links, cleaning up docs and READMEs.
- Clarify warm boot attack mitigations and scope for Bellatrix in
threat model.
For full change log [see](https://github.com/tillitis/tillitis-key1/compare/TK1-23.03.2...TK1-24.03)
## TK1-23.03.2
This is the official release of the "Bellatrix" version of the
@ -234,8 +303,8 @@ This bug fix release contains the following changes:
- Change the firmware protocol max frame size back to 128 bytes
- Correct a bug with the reading out of UDS
## TK1-23.03
This is the official release of the "Bellatrix" version of
the Tillitis TKey device. This version is ready for general
use.
@ -249,7 +318,6 @@ shasum -a256 application_fpga.bin
f11d6b0f57c5405598206dcfea284008413391a2c51f124a2e2ae8600cb78f0b application_fpga.bin
```
### New and improved functionality
- (ALL) The TKey HW design, FW, protocol and first applications has
@ -313,10 +381,9 @@ f11d6b0f57c5405598206dcfea284008413391a2c51f124a2e2ae8600cb78f0b application_fp
- (TOOLS) There is now a version of iceprog able to write to the FPGA
bitstream to the NVCM and lock the NVCM from external access
### Bugs fixed
- No known bugs have been fixed. Numerous issues has been closed.
- No known bugs have been fixed. Numerous issues has been closed.
### Limitations
@ -324,7 +391,6 @@ f11d6b0f57c5405598206dcfea284008413391a2c51f124a2e2ae8600cb78f0b application_fp
cryptographically secure. It his however randomized every time
a TKey device is powered up.
## engineering-release-2
### New and improved functionality

View file

@ -1,149 +0,0 @@
# Toolchain setup
**NOTE:** Documentation migrated to dev.tillitis.se, this is kept for
history. This is likely to be outdated.
Here are instructions for setting up the tools required to build the
project. Tested on Ubuntu 22.10.
## General development environment
The following is intended to be a complete list of the packages that
are required for doing all of the following:
- building and developing [TKey device and client
apps](https://github.com/tillitis/tillitis-key1-apps)
- building our [QEMU machine](https://github.com/tillitis/qemu/tree/tk1)
(useful for apps dev)
- building and developing firmware and FPGA gateware (which also
requires building the toolchain below)
```
sudo apt install build-essential clang lld llvm bison flex libreadline-dev \
gawk tcl-dev libffi-dev git mercurial graphviz \
xdot pkg-config python3 libftdi-dev \
python3-dev libeigen3-dev \
libboost-dev libboost-filesystem-dev \
libboost-thread-dev libboost-program-options-dev \
libboost-iostreams-dev cmake libusb-1.0-0-dev \
ninja-build libglib2.0-dev libpixman-1-dev \
golang clang-format \
gcc-arm-none-eabi libnewlib-arm-none-eabi \
libstdc++-arm-none-eabi-newlib
```
## Device permissions
To allow sudo-less programming, you can install a udev rule that will
assign the tkey programmer, and also an unprogrammed CH552, to the
dialout group. You will also need to add your user to this group:
```
sudo cp contrib/99-tillitis.rules /etc/udev/rules.d
sudo udevadm control --reload-rules
sudo usermod -aG dialout ${USER}
```
To apply the new group, log out and then log back in.
You can check the device permissions to determine if the group was
successfully applied. First, use lsusb to find the location of the
programmer:
```
lsusb -d 1209:8886
Bus 001 Device 023: ID 1209:8886 Generic TP-1
```
Then, you can check the permissions by using the bus and device
number reported above. Note that this pair is ephemeral and may
change after every device insertion:
```
ls -l /dev/bus/usb/001/023
crw-rw---- 1 root dialout 189, 22 Feb 16 14:58 /dev/bus/usb/001/023
```
## Gateware: Yosys/Icestorm toolchain
If the LED of your TKey is steady white when you plug it, then the
firmware is running and it's already usable! If you want to develop
TKey apps, then only the above general development environment is
needed.
Compiling and installing Yosys and friends is only needed if your TKey
is not already running the required firmware and FPGA gateware, or if
you want to do development on these components.
These steps are used to build and install the
[icestorm](http://bygone.clairexen.net/icestorm/) toolchain. The
binaries are installed in `/usr/local`. Note that if you have or
install other versions of these tools locally, they could conflict
(case in point: `yosys` installed on MacOS using brew).
git clone https://github.com/YosysHQ/icestorm
cd icestorm
git checkout d20a5e9001f46262bf0cef220f1a6943946e421d
make -j$(nproc)
sudo make install
cd ..
# Custom iceprog for the RPi 2040-based programmer (will be upstreamed).
# Note: install dependencies for building tillitis-iceprog on Ubuntu:
# sudo apt install libftdi-dev libusb-1.0-0-dev
git clone -b interfaces https://github.com/tillitis/icestorm tillitis--icestorm
cd tillitis--icestorm/iceprog
make
sudo make PROGRAM_PREFIX=tillitis- install
cd ../..
git clone https://github.com/YosysHQ/yosys
cd yosys
git checkout yosys-0.26
make -j$(nproc)
sudo make install
cd ..
git clone https://github.com/YosysHQ/nextpnr
cd nextpnr
git checkout nextpnr-0.5
cmake -DARCH=ice40 -DCMAKE_INSTALL_PREFIX=/usr/local .
make -j$(nproc)
sudo make install
cd ..
References:
* http://bygone.clairexen.net/icestorm/
## Firmware: riscv toolchain
The TKey implements a [picorv32](https://github.com/YosysHQ/picorv32)
soft core CPU, which is a RISC-V microcontroller with the C
instructions and Zmmul extension, multiply without divide
(RV32ICZmmul). You can read
[more](https://www.sifive.com/blog/all-aboard-part-1-compiler-args)
about it.
The project uses the LLVM/Clang suite and version 15 or later is
required. As of writing Ubuntu 22.10 has version 15 packaged. You may
be able to get it installed on older Ubuntu and Debian using the
instructions on https://apt.llvm.org/ . There are also binary releases
here: https://github.com/llvm/llvm-project/releases
References:
* https://github.com/YosysHQ/picorv32
If your available `objcopy` and `size` commands is anything other than
the default `llvm-objcopy` and `llvm-size` define `OBJCOPY` and `SIZE`
to whatever they're called on your system before calling `make`.
## CH552 USB to Serial firmware
The USB to Serial firmware runs on the CH552 microcontroller, and
provides a USB CDC profile which should work with the default drivers
on all major operating systems. MTA1-USB-V1 and TK-1 devices come
with the CH552 microcontroller pre-programmed.
Toolchain setup and build instructions for this firmware are detailed
in the
[ch552_fw directory](../hw/usb_interface/ch552_fw/README.md)

View file

@ -6,8 +6,8 @@
# HW targets as well as its firmware.
#
#
# Copyright (C) 2022-2024 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#
# Please note: When creating a new cores and adding more testbenches,
@ -43,6 +43,10 @@ CC = clang
LIBDIR ?= tkey-libs
# The preloaded app in slot 0. Must be defined. Firmware depends on
# it. Change this if you want another first preloaded app.
DEFAULT_APP ?= $(P)/apps/defaultapp.bin
CFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
@ -119,8 +123,11 @@ VERILOG_SRCS = \
PICORV32_SRCS = \
$(P)/core/picorv32/rtl/picorv32.v
# Mention mgmt_app_digest.h explicitly since it needs to be generated.
FIRMWARE_DEPS = \
$(P)/fw/tk1/proto.h
$(P)/fw/tk1/*.h \
$(P)/fw/tk1/mgmt_app_digest.h
FIRMWARE_OBJS = \
$(P)/fw/tk1/main.o \
@ -134,6 +141,7 @@ FIRMWARE_OBJS = \
$(P)/fw/tk1/partition_table.o \
$(P)/fw/tk1/auth_app.o \
$(P)/fw/tk1/rng.o \
$(P)/fw/tk1/reset.o \
$(P)/fw/tk1/preload_app.o \
$(P)/fw/tk1/mgmt_app.o
@ -175,6 +183,19 @@ secret:
cd data;../tools/tpt/tpt.py
.PHONY: secret
# -------------------------------------------------------------------
# Build tools
# -------------------------------------------------------------------
# .PHONY to let go build handle deps and rebuilds
.PHONY: tools/tkeyimage/tkeyimage
tools/tkeyimage/tkeyimage:
go build -C $(P)/tools/tkeyimage
.PHONY: tools/b2s/b2s
tools/b2s/b2s:
go build -C $(P)/tools/b2s
#-------------------------------------------------------------------
# Firmware generation.
# Included in the bitstream.
@ -184,17 +205,30 @@ LDFLAGS = \
-Wl,--cref,-M \
-L $(LIBDIR) -lcommon -lblake2s
QEMU_LDFLAGS = \
-T $(P)/fw/tk1/qemu_firmware.lds \
-Wl,--cref,-M \
-L $(LIBDIR) -lcommon -lblake2s
# Common libraries the firmware and testfw depend on. See
# https://github.com/tillitis/tkey-libs/
.PHONY: tkey-libs
tkey-libs:
make -C $(LIBDIR)
# Device app used as preloaded app
$(DEFAULT_APP):
make -C apps
# Build a complete filesystem image
flash_image.bin: tools/tkeyimage/tkeyimage $(DEFAULT_APP)
./tools/tkeyimage/tkeyimage -f -app0 $(DEFAULT_APP) -o $@
$(FIRMWARE_OBJS): $(FIRMWARE_DEPS)
$(TESTFW_OBJS): $(FIRMWARE_DEPS)
#firmware.elf: CFLAGS += -DTKEY_DEBUG
firmware.elf: tkey-libs $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds
firmware.elf: tkey-libs $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds flash_image.bin
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@ > $(basename $@).map
simfirmware.elf: CFLAGS += -DSIMULATION
@ -205,8 +239,13 @@ qemu_firmware.elf: CFLAGS += -DQEMU_DEBUG
qemu_firmware.elf: ASFLAGS += -DQEMU_DEBUG
qemu_firmware.elf: CFLAGS += -DQEMU_SYSCALL
qemu_firmware.elf: ASFLAGS += -DQEMU_SYSCALL
qemu_firmware.elf: firmware.elf
mv firmware.elf qemu_firmware.elf
qemu_firmware.elf: tkey-libs $(FIRMWARE_OBJS) $(P)/fw/tk1/qemu_firmware.lds flash_image.bin
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(QEMU_LDFLAGS) -o $@ > $(basename $@).map
# Generate the file containing the digest for the obligatory default
# app in slot 0.
$(P)/fw/tk1/mgmt_app_digest.h: $(DEFAULT_APP) tools/b2s/b2s
./tools/b2s/b2s -c -m $(DEFAULT_APP) > $@
# Create compile_commands.json for clangd and LSP
.PHONY: clangd
@ -249,11 +288,11 @@ bram_fw.hex:
$(ICESTORM_PATH)icebram -v -g 32 $(BRAM_FW_SIZE) > $@
firmware.hex: firmware.bin firmware_size_mismatch
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
python3 $(P)/tools/makehex.py $< $(BRAM_FW_SIZE) > $@
simfirmware.hex: simfirmware.bin simfirmware_size_mismatch
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
python3 $(P)/tools/makehex.py $< $(BRAM_FW_SIZE) > $@
testfw.hex: testfw.bin testfw_size_mismatch
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
python3 $(P)/tools/makehex.py $< $(BRAM_FW_SIZE) > $@
.PHONY: check-binary-hashes
check-binary-hashes:
@ -325,6 +364,7 @@ fmt: $(FPGA_VERILOG_SRCS) $(SIM_VERILOG_SRCS) $(VERILATOR_VERILOG_SRCS) $(VERILO
checkfmt: $(FPGA_VERILOG_SRCS) $(SIM_VERILOG_SRCS) $(VERILATOR_VERILOG_SRCS) $(VERILOG_SRCS)
make -C fw/tk1 checkfmt
make -C fw/testfw checkfmt
make -C apps checkfmt
$(FORMAT) $(CHECK_FORMAT_FLAGS) $^ 2>&1 | \
grep "Needs formatting" && exit 1 || true
.PHONY: checkfmt
@ -389,7 +429,7 @@ synth.json: $(FPGA_VERILOG_SRCS) $(VERILOG_SRCS) $(PICORV32_SRCS) bram_fw.hex
application_fpga_par.json: synth.json $(P)/data/$(PIN_FILE)
$(NEXTPNR_PATH)nextpnr-ice40 \
-l application_fpga_par.txt \
--seed 9416596747216415304 \
--seed 2945058561865725735 \
--freq $(TARGET_FREQ) \
--ignore-loops \
--up5k \
@ -464,18 +504,23 @@ tb_application_fpga: $(SIM_VERILOG_SRCS) \
# FPGA device programming.
#-------------------------------------------------------------------
prog_flash: check-hardware application_fpga.bin
sudo tillitis-iceprog application_fpga.bin
prog_flash: check-hardware application_fpga.bin flash_image.bin
tillitis-iceprog flash_image.bin
tillitis-iceprog application_fpga.bin
.PHONY: prog_flash
prog_flash_bs: check-hardware application_fpga.bin
tillitis-iceprog application_fpga.bin
.PHONY: prog_flash_bs
prog_flash_testfw: check-hardware application_fpga_testfw.bin
sudo tillitis-iceprog application_fpga_testfw.bin
tillitis-iceprog application_fpga_testfw.bin
.PHONY: prog_flash_testfw
check-hardware:
@sudo tillitis-iceprog -t >/dev/null 2>&1 || \
@tillitis-iceprog -t >/dev/null 2>&1 || \
{ echo "Programmer not plugged in or not accessible"; false; }
@if sudo tillitis-iceprog -t 2>&1 | grep -qi "^flash.id:\( 0x\(00\|ff\)\)\{4\}"; then \
@if tillitis-iceprog -t 2>&1 | grep -qi "^flash.id:\( 0x\(00\|ff\)\)\{4\}"; then \
echo "No USB stick in the programmer?"; false; else true; fi
.PHONY: check-hardware
@ -499,6 +544,10 @@ clean: clean_sim clean_fw clean_tb
rm -f lint_issues.txt
rm -f tools/tpt/*.hex
rm -rf tools/tpt/__pycache__
make -C apps clean
rm -f fw/tk1/mgmt_app_digest.h
rm -f flash_image.bin
.PHONY: clean
clean_fw:
@ -506,7 +555,7 @@ clean_fw:
rm -f $(FIRMWARE_OBJS)
rm -f testfw.{elf,map,bin,hex}
rm -f $(TESTFW_OBJS)
rm -f qemu_firmware.elf
rm -f qemu_firmware.{elf,map,bin,hex}
make -C tkey-libs clean
.PHONY: clean_fw
@ -547,7 +596,8 @@ help:
@echo "tb_application_fpga Build testbench simulation for the design"
@echo "lint Run lint on Verilog source files."
@echo "tb Run all testbenches"
@echo "prog_flash Program device flash with FGPA bitstream including firmware (using the RPi Pico-based programmer)."
@echo "prog_flash Program device flash with FGPA bitstream (including firmware), partition table, and defaultapp.bin (using the RPi Pico-based programmer)."
@echo "prog_flash_bs Program device flash with FGPA bitstream including firmware (using the RPi Pico-based programmer)."
@echo "prog_flash_testfw Program device flash as above, but with testfw."
@echo "clean Delete all generated files."
@echo "clean_fw Delete only generated files for firmware. Useful for fw devs."

View file

@ -1,4 +1,4 @@
# TKey hardware design
## TKey hardware design
![The Application FPGA block diagram](../../doc/images/application_fpga_block_diagram.png)
@ -16,8 +16,9 @@ firmware, application and system call. Each mode give access to a
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
their own `README.md` file documenting them and their API in detail.
The rest of the components are under `cores`, except the firmware,
which is under `fw/tk1`. 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
@ -38,6 +39,11 @@ Rough memory map:
| Syscall | 0xe1 |
| TK1 | 0xff |
## Firmware
Firmware is kept in ROM. See the [Firmware implementation
notes](fw/README.md).
## `clk_reset_gen`
Generator for system clock and system reset.

View file

@ -1 +1 @@
c770fe25034655241d9e0152b03fcf691c548bc50d30b574a5213abc5b36fe25 application_fpga.bin
099f54fe1cbfbfd1d235af2d838340e1daa78de8b20eeae475ce975a123ddae7 application_fpga.bin

View file

@ -0,0 +1,139 @@
# SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
P := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
LIBDIR ?= ../tkey-libs
OBJCOPY ?= llvm-objcopy
CC = clang
CFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mcmodel=medany \
-static \
-std=gnu99 \
-Os \
-ffast-math \
-fno-common \
-fno-builtin-printf \
-fno-builtin-putchar \
-fno-builtin-memcpy \
-nostdlib \
-mno-relax \
-Wall \
-Wpedantic \
-Wno-language-extension-token \
-Werror \
-flto \
-g \
-I $(LIBDIR)/include \
-I $(LIBDIR) \
-I include \
-I ../
AS = clang
ASFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mno-relax
LDFLAGS = \
-T $(LIBDIR)/app.lds \
-L $(LIBDIR) -lcrt0 -lcommon -lmonocypher -lblake2s
.PHONY: all
all: defaultapp.bin loopbackapp.bin reset_test.bin testapp.bin testloadapp.bin
# Turn elf into bin for device
%.bin: %.elf
$(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $^ $@
chmod a-x $@
.PHONY: tkey-libs
tkey-libs:
make -C $(LIBDIR)
OBJS=syscall.o
# syscall.o: syscall.S
# $(CC) $(CFLAGS) $(DEFAULTAPP_OBJS) $(LDFLAGS) -o $@
# defaultapp
DEFAULTAPP_FMTFILES = *.[ch]
DEFAULTAPP_OBJS = \
$(P)/defaultapp/main.o
defaultapp.elf: tkey-libs $(OBJS) $(DEFAULTAPP_OBJS)
$(CC) $(CFLAGS) $(OBJS) $(DEFAULTAPP_OBJS) $(LDFLAGS) -o $@
# loopbackapp
LOOPBACKAPP_OBJS = \
$(P)/loopbackapp/main.o
loopbackapp.elf: tkey-libs $(LOOPBACKAPP_OBJS)
$(CC) $(CFLAGS) $(LOOPBACKAPP_OBJS) $(LDFLAGS) -o $@
# reset_test
RESET_TEST_FMTFILES = *.[ch]
RESET_TEST_OBJS = \
$(P)/reset_test/main.o
reset_test.elf: tkey-libs $(RESET_TEST_OBJS)
$(CC) $(CFLAGS) $(OBJS) $(RESET_TEST_OBJS) $(LDFLAGS) -o $@
# testapp
TESTAPP_OBJS = \
$(P)/testapp/main.o
testapp.elf: tkey-libs $(TESTAPP_OBJS)
$(CC) $(CFLAGS) $(OBJS) $(TESTAPP_OBJS) $(LDFLAGS) -o $@
# testloadapp
TESTLOADAPP_OBJS = \
$(P)/testloadapp/main.o
testloadapp.elf: tkey-libs $(TESTLOADAPP_OBJS)
$(CC) $(CFLAGS) $(OBJS) $(TESTLOADAPP_OBJS) $(LDFLAGS) -o $@
.PHONY: fmt
fmt:
clang-format --dry-run --ferror-limit=0 defaultapp/*.[ch]
clang-format --verbose -i defaultapp/*.[ch]
clang-format --dry-run --ferror-limit=0 loopbackapp/*.[ch]
clang-format --verbose -i loopbackapp/*.[ch]
clang-format --dry-run --ferror-limit=0 reset_test/*.[ch]
clang-format --verbose -i reset_test/*.[ch]
clang-format --dry-run --ferror-limit=0 testapp/*.[ch]
clang-format --verbose -i testapp/*.[ch]
clang-format --dry-run --ferror-limit=0 testloadapp/*.[ch]
clang-format --verbose -i testloadapp/*.[ch]
.PHONY: checkfmt
checkfmt:
clang-format --dry-run --ferror-limit=0 defaultapp/*.[ch]
clang-format --dry-run --ferror-limit=0 loopbackapp/*.[ch]
clang-format --dry-run --ferror-limit=0 reset_test/*.[ch]
clang-format --dry-run --ferror-limit=0 testapp/*.[ch]
clang-format --dry-run --ferror-limit=0 testloadapp/*.[ch]
.PHONY: clean
clean:
rm -f *.elf *.bin $(OBJS) $(DEFAULTAPP_OBJS) $(LOOPBACKAPP_OBJS) \
$(RESET_TEST_OBJS) $(TESTAPP_OBJS) $(TESTLOADAPP_OBJS)

View file

@ -0,0 +1,36 @@
# Test applications
- `defaultapp`: Immediately resets the TKey with the intention to
start an app from the client, replicating the behaviour of earlier
generations.
- `testapp`: Runs through a couple of tests that are now impossible
to do in the `testfw`.
- `reset_test`: Interactively test different reset scenarios.
- `testloadapp`: Interactively test management app things like
installing an app (hardcoded for a small happy blinking app, see
`blink.h` for the entire binary!) and to test verified boot.
## Build
```
$ make
```
will build all the .elf and .bin files on the top level.
## Use
Use `tkey-runapp` from
[tkey-devtools](https://github.com/tillitis/tkey-devtools) to load the
apps:
```
$ tkey-runapp testapp.bin
```
All of these test apps are controlled through the USB CDC, typically
by running picocom or similar terminal program, like:
```
$ picocom /dev/ttyACM1
```

View file

@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <fw/tk1/reset.h>
#include <fw/tk1/syscall_num.h>
#include <syscall.h>
#include <tkey/debug.h>
#include <tkey/led.h>
int main(void)
{
struct reset rst = {0};
led_set(LED_BLUE);
rst.type = START_CLIENT;
syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0);
}

View file

@ -0,0 +1,143 @@
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stdbool.h>
#include <stdint.h>
#include <tkey/assert.h>
#include <tkey/io.h>
#include <tkey/led.h>
#include <tkey/lib.h>
#define BUFSIZE 256
#define HEADER_SIZE 2
#define HID_PACKET_SIZE 64
#define MAX_PAYLOAD_SIZE 64
#define SLEEPTIME 100000
void sleep(uint32_t n)
{
for (volatile int i = 0; i < n; i++)
;
}
int main(void)
{
uint8_t available = 0;
uint8_t cmdbuf[BUFSIZE] = {0};
enum ioend endpoint = IO_NONE;
bool waiting_for_more_data = false;
uint8_t dest_endpoint = IO_NONE;
uint8_t payload_length = 0;
uint8_t payload_left = 0;
uint8_t payloadbuf[MAX_PAYLOAD_SIZE] = {0};
uint8_t first_packet_len = HID_PACKET_SIZE - HEADER_SIZE;
uint8_t endpoints = IO_DEBUG;
led_set(LED_BLUE);
// Give time to CH552 to settle USB enumeration at power on
sleep(SLEEPTIME * 5);
// Setup available endpoints
endpoints |= IO_CDC | IO_FIDO;
config_endpoints(endpoints);
while (1) {
// Wait for data
if (readselect(endpoints, &endpoint, &available) != 0) {
assert(1 == 2);
}
switch (endpoint) {
case IO_CDC:
cmdbuf[0] = IO_CDC;
cmdbuf[1] = available;
if (read(IO_CDC, cmdbuf + 2, BUFSIZE - 2, available) <
0) {
assert(1 == 2);
}
write(IO_DEBUG, cmdbuf, available + 2);
memset(cmdbuf, 0, BUFSIZE);
break;
case IO_FIDO:
cmdbuf[0] = IO_FIDO;
cmdbuf[1] = available;
if (read(IO_FIDO, cmdbuf + 2, BUFSIZE - 2, available) <
0) {
assert(1 == 2);
}
write(IO_DEBUG, cmdbuf, available + 2);
memset(cmdbuf, 0, BUFSIZE);
break;
case IO_CCID:
cmdbuf[0] = IO_CCID;
cmdbuf[1] = available;
if (read(IO_CCID, cmdbuf + 2, BUFSIZE - 2, available) <
0) {
assert(1 == 2);
}
write(IO_DEBUG, cmdbuf, available + 2);
memset(cmdbuf, 0, BUFSIZE);
break;
case IO_DEBUG:
if (available != HID_PACKET_SIZE) {
led_set(LED_RED);
while (1)
;
}
if (read(IO_DEBUG, cmdbuf, BUFSIZE, available) < 0) {
assert(1 == 2);
}
if (!waiting_for_more_data) {
dest_endpoint = cmdbuf[0];
payload_length = cmdbuf[1];
// Check that destination endpoint is ok
if (dest_endpoint != IO_CDC &&
dest_endpoint != IO_FIDO &&
dest_endpoint != IO_CCID) {
led_set(LED_RED);
while (1)
;
}
// Check payload size
if (payload_length > MAX_PAYLOAD_SIZE) {
led_set(LED_RED);
while (1)
;
}
// Complete payload fits in this packet
if (payload_length <= first_packet_len) {
write(dest_endpoint, cmdbuf + 2,
payload_length);
memset(cmdbuf, 0, BUFSIZE);
} else { // More payload will come in next
// packet
memcpy(payloadbuf, cmdbuf + 2,
first_packet_len);
payload_left =
payload_length - first_packet_len;
waiting_for_more_data = true;
}
} else {
memcpy(payloadbuf + first_packet_len, cmdbuf,
payload_left);
write(dest_endpoint, payloadbuf,
payload_length);
memset(payloadbuf, 0, MAX_PAYLOAD_SIZE);
memset(cmdbuf, 0, BUFSIZE);
waiting_for_more_data = false;
}
break;
default:
break;
}
}
}

View file

@ -1,9 +1,11 @@
/*
* Copyright (C) 2022, 2023 - Tillitis AB
* SPDX-License-Identifier: GPL-2.0-only
*/
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <fw/tk1/proto.h>
#include <fw/tk1/reset.h>
#include <fw/tk1/syscall_num.h>
#include <stdint.h>
#include <syscall.h>
#include <tkey/assert.h>
#include <tkey/debug.h>
#include <tkey/io.h>
@ -11,11 +13,6 @@
#include <tkey/lib.h>
#include <tkey/tk1_mem.h>
#include "../testapp/syscall.h"
#include "../tk1/proto.h"
#include "../tk1/resetinfo.h"
#include "../tk1/syscall_num.h"
// Converts a single hex character to its integer value
static uint8_t hex_char_to_byte(uint8_t c)
{

View file

@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include "../tk1/picorv32/custom_ops.S"
#include "../fw/tk1/picorv32/custom_ops.S"
.section ".text"
.globl syscall

View file

@ -1,8 +1,9 @@
/*
* Copyright (C) 2022, 2023 - Tillitis AB
* SPDX-License-Identifier: GPL-2.0-only
*/
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <fw/tk1/proto.h>
#include <fw/tk1/reset.h>
#include <fw/tk1/syscall_num.h>
#include <stdint.h>
#include <tkey/assert.h>
#include <tkey/io.h>
@ -10,9 +11,6 @@
#include <tkey/lib.h>
#include <tkey/tk1_mem.h>
#include "../tk1/proto.h"
#include "../tk1/resetinfo.h"
#include "../tk1/syscall_num.h"
#include "syscall.h"
#define USBMODE_PACKET_SIZE 64
@ -20,6 +18,7 @@
// 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 *tk1version = (volatile uint32_t *)TK1_MMIO_TK1_VERSION;
volatile uint32_t *uds = (volatile uint32_t *)TK1_MMIO_UDS_FIRST;
volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
volatile uint32_t *udi = (volatile uint32_t *)TK1_MMIO_TK1_UDI_FIRST;
@ -98,6 +97,9 @@ int main(void)
reverseword(&name);
write(IO_CDC, (const uint8_t *)&name, 4);
puts(IO_CDC, "\r\n");
puts(IO_CDC, "Version: ");
putinthex(IO_CDC, *tk1version);
puts(IO_CDC, "\r\n");
uint32_t zeros[8];
memset(zeros, 0, 8 * 4);
@ -124,8 +126,8 @@ int main(void)
// But a syscall to get parts of UDI should be able to run
int vidpid = syscall(TK1_SYSCALL_GET_VIDPID, 0, 0, 0);
if (vidpid != 0x00010203) {
failmsg("Expected VID/PID to be 0x00010203");
if (vidpid != 0x073570c0) {
failmsg("Expected VID/PID to be 0x073570c0");
anyfailed = 1;
}
@ -145,7 +147,7 @@ int main(void)
}
puts(IO_CDC, "done.\r\n");
puts(IO_CDC, "\r\nReading from storage area...");
puts(IO_CDC, "\r\nReading data from storage area...");
uint8_t in_data[14] = {0};
if (syscall(TK1_SYSCALL_READ_DATA, 0, (uint32_t)in_data,
@ -158,6 +160,28 @@ int main(void)
}
puts(IO_CDC, "done.\r\n");
puts(IO_CDC, "\r\nErasing written data from storage area...");
if (syscall(TK1_SYSCALL_ERASE_DATA, 0, 4096, 0) != 0) {
failmsg("Failed to erase storage area");
}
puts(IO_CDC, "done.\r\n");
puts(IO_CDC, "\r\nVerify erased storage area data...");
if (syscall(TK1_SYSCALL_READ_DATA, 0, (uint32_t)in_data,
sizeof(in_data)) != 0) {
failmsg("Failed to write to storage area");
}
uint8_t check_data[sizeof(in_data)] = {0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff};
if (!memeq(in_data, check_data, sizeof(check_data))) {
failmsg("Failed to read back data from storage area");
anyfailed = 1;
}
puts(IO_CDC, "done.\r\n");
puts(IO_CDC, "\r\nDeallocating storage area...");
if (syscall(TK1_SYSCALL_DEALLOC_AREA, 0, 0, 0) != 0) {
@ -190,8 +214,8 @@ int main(void)
}
puts(IO_CDC, "\r\nTesting timer... 3");
// Matching clock at 21 MHz, giving us timer in seconds
*timer_prescaler = 21 * 1000000;
// Matching clock at 24 MHz, giving us timer in seconds
*timer_prescaler = 24 * 1000000;
// Test timer expiration after 1s
*timer = 1;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#ifndef BLINK_APP_H
#define BLINK_APP_H

View file

@ -1,15 +1,19 @@
// SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <blake2s/blake2s.h>
#include <fw/tk1/reset.h>
#include <fw/tk1/syscall_num.h>
#include <monocypher/monocypher-ed25519.h>
#include <stdint.h>
#include <tkey/assert.h>
#include <tkey/debug.h>
#include <tkey/led.h>
#include <tkey/lib.h>
#include <tkey/tk1_mem.h>
#include "../testapp/syscall.h"
#include "../tk1/resetinfo.h"
#include "../tk1/syscall_num.h"
#include "blink.h"
#include "tkey/assert.h"
#include "syscall.h"
// clang-format off
static volatile uint32_t *cdi = (volatile uint32_t *) TK1_MMIO_TK1_CDI_FIRST;
@ -150,7 +154,11 @@ void reset_from_client(void)
rst.type = START_CLIENT;
syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0);
// Give the next in chain something to look at.
memset(rst.next_app_data, 17, sizeof(rst.next_app_data));
syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, sizeof(rst.next_app_data),
0);
}
int main(void)
@ -161,6 +169,8 @@ int main(void)
uint8_t available;
uint8_t in = 0;
led_set(LED_BLUE);
// Generate a key pair from CDI
crypto_ed25519_key_pair(secret_key, pubkey, (uint8_t *)cdi);

View file

@ -9,8 +9,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
// support for mode based access control.
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
#
#
# Author: Joachim Strombergson
# Copyright (C) 2024 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#===================================================================

View file

@ -11,8 +11,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -7,8 +7,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
#
#
# Author: Joachim Strombergson
# Copyright (C) 2022 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#===================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================
@ -101,7 +101,7 @@ module tk1 #(
localparam TK1_NAME0 = 32'h746B3120; // "tk1 "
localparam TK1_NAME1 = 32'h6d6b6466; // "mkdf"
localparam TK1_VERSION = 32'h00000005;
localparam TK1_VERSION = 32'h00000006;
localparam FW_RAM_FIRST = 32'hd0000000;
localparam FW_RAM_LAST = 32'hd0000fff; // 4 KB

View file

@ -16,8 +16,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -7,8 +7,8 @@
//
//
// Author: Claire Xenia Wolf
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -8,8 +8,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strömbergson.
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
#
#
# Author: Joachim Strombergson
# Copyright (C) 2023 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#===================================================================

View file

@ -6,8 +6,8 @@
# ------
# Program that generates hex memory file read by the memory model.
#
# Copyright (C) 2024 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#=======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
#
#
# Author: Joachim Strombergson
# Copyright (C) 2022 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#===================================================================

View file

@ -9,8 +9,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -7,7 +7,7 @@
#
# Author: Joachim Strombergson
# Copyright (C) 2023 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-License-Identifier: BSD-2-Clause
#
#===================================================================

View file

@ -24,6 +24,11 @@ in order to hit the center of the bits. For example, a clock of 18 MHz
and a target bit rate of 62500 bps yields:
Divisor = 18E6 / 62500 = 288
The UART core includes hardware flow control in the form of two CTS
lines. One input that the core will check before sending bytes, and
one output to signal to a connected device that the internal FIFO is
full. The CTS are active-low.
## API
```

View file

@ -227,7 +227,7 @@ module uart (
end
ADDR_TX_STATUS: begin
tmp_read_data = {31'h0, core_txd_ready & ch552_cts_reg[1]};
tmp_read_data = {31'h0, core_txd_ready & !ch552_cts_reg[1]};
end
default: begin

View file

@ -17,8 +17,8 @@
//
// Author: Joachim Strombergson
// Copyright (c) 2014, Secworks Sweden AB
//
// SPDX-License-Identifier: BSD-2-Clause
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
@ -79,6 +79,7 @@ module uart_core (
parameter ERX_BITS = 2;
parameter ERX_STOP = 3;
parameter ERX_SYN = 4;
parameter ERX_ERR = 5;
parameter ETX_IDLE = 0;
parameter ETX_START = 1;
@ -111,6 +112,9 @@ module uart_core (
reg rxd_syn_new;
reg rxd_syn_we;
reg rxd_stop_bit_reg;
reg rxd_stop_bit_we;
reg [ 2 : 0] erx_ctrl_reg;
reg [ 2 : 0] erx_ctrl_new;
reg erx_ctrl_we;
@ -176,7 +180,9 @@ module uart_core (
rxd_bit_ctr_reg <= 4'h0;
rxd_bitrate_ctr_reg <= 16'h0;
rxd_syn_reg <= 0;
erx_ctrl_reg <= ERX_IDLE;
erx_ctrl_reg <= ERX_ERR;
rxd_stop_bit_reg <= 1'h0;
txd_reg <= 1;
txd_byte_reg <= 8'h0;
@ -210,6 +216,10 @@ module uart_core (
erx_ctrl_reg <= erx_ctrl_new;
end
if (rxd_stop_bit_we) begin
rxd_stop_bit_reg <= rxd_reg;
end
if (txd_we) begin
txd_reg <= txd_new;
end
@ -341,10 +351,23 @@ module uart_core (
rxd_byte_we = 0;
rxd_syn_new = 0;
rxd_syn_we = 0;
erx_ctrl_new = ERX_IDLE;
erx_ctrl_new = ERX_ERR;
erx_ctrl_we = 0;
rxd_stop_bit_we = 0;
case (erx_ctrl_reg)
// Wait until the RX lines goes high before accepting new frames
ERX_ERR: begin
if (rxd_reg) begin
// RX line in idle state
erx_ctrl_new = ERX_IDLE;
erx_ctrl_we = 1;
end
end
ERX_IDLE: begin
if (!rxd_reg) begin
// Possible start bit detected.
@ -387,32 +410,36 @@ module uart_core (
end
else begin
rxd_bitrate_ctr_rst = 1;
if (rxd_bit_ctr_reg < data_bits) begin
rxd_bitrate_ctr_rst = 1;
rxd_bit_ctr_inc = 1;
rxd_byte_we = 1; // We are in the middle of a data bit, make a sample
rxd_bit_ctr_inc = 1;
rxd_byte_we = 1; // We are in the middle of a data bit, make a sample
end
else begin
erx_ctrl_new = ERX_STOP; // We are now in the middle of the stop bit
erx_ctrl_we = 1;
erx_ctrl_we = 1;
rxd_stop_bit_we = 1; // sample stop bit
end
end
end
ERX_STOP: begin
// stop_bits can be removed from line below if we are only using one stop bit
if (rxd_bitrate_ctr_reg < (bit_rate * stop_bits)) begin
rxd_bitrate_ctr_inc = 1;
end
// Check if the first stop bit is valid.
// Note: Ignores stop bit 1.5 and 2, if present.
if (rxd_stop_bit_reg) begin
rxd_syn_new = 1;
rxd_syn_we = 1;
erx_ctrl_new = ERX_SYN;
erx_ctrl_we = 1;
end
else begin
rxd_bitrate_ctr_rst = 1;
rxd_syn_new = 1;
rxd_syn_we = 1;
erx_ctrl_new = ERX_SYN;
erx_ctrl_we = 1;
// Framing error, go to ERR state
erx_ctrl_new = ERX_ERR;
erx_ctrl_we = 1;
end
end

View file

@ -7,7 +7,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (c) 2022, Tillitis AB
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
@ -105,7 +106,7 @@ module uart_fifo (
out_ptr_reg <= 9'h0;
byte_ctr_reg <= 9'h0;
in_ack_reg <= 1'h0;
fpga_cts_reg <= 1'h1;
fpga_cts_reg <= 1'h0;
end
else begin
in_ack_reg <= in_ack_new;
@ -127,10 +128,10 @@ module uart_fifo (
end
if (byte_ctr_reg >= 9'd486) begin // FIFO is filled to ~95% or more
fpga_cts_reg <= 0; // Signal to not send more data
fpga_cts_reg <= 1; // Signal to not send more data
end
else begin
fpga_cts_reg <= 1; // Signal to send more data
fpga_cts_reg <= 0; // Signal to send more data
end
end

View file

@ -8,6 +8,7 @@
// Author: Joachim Strombergson
// Copyright (c) 2014, Secworks Sweden AB
// All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
@ -238,9 +239,10 @@ module tb_uart ();
//----------------------------------------------------------------
// transmit_byte
//
// Transmit a byte of data to the DUT receive port.
// Transmit a byte of data to the DUT receive port. With or without a valid
// stop bit.
//----------------------------------------------------------------
task transmit_byte(input [7 : 0] data);
task transmit_byte(input [7 : 0] data, input invalid_stop_bit);
integer i;
begin
$display("*** Transmitting byte 0x%02x to the dut.", data);
@ -260,8 +262,13 @@ module tb_uart ();
end
// Send two stop bits. I.e. two bit times high (mark) value.
$display("*** Transmitting two stop bits.");
tb_rxd = 1;
if (invalid_stop_bit) begin
$display("*** Transmitting INVALID stop bits.");
tb_rxd = 0;
end else begin
$display("*** Transmitting stop bits.");
tb_rxd = 1;
end
#(2 * CLK_PERIOD * dut.DEFAULT_BIT_RATE * dut.DEFAULT_STOP_BITS);
$display("*** End of transmission.");
end
@ -272,26 +279,46 @@ module tb_uart ();
// check_transmit
//
// Transmits a byte and checks that it was captured internally
// by the dut.
// by the dut. Include option to set stop bit to invalid.
//----------------------------------------------------------------
task check_transmit(input [7 : 0] data);
task check_transmit(input [7 : 0] data, input invalid_stop_bit);
begin
tc_ctr = tc_ctr + 1;
transmit_byte(data);
transmit_byte(data, invalid_stop_bit);
if (dut.core.rxd_byte_reg == data) begin
$display("*** Correct data: 0x%01x captured by the dut.", dut.core.rxd_byte_reg);
end
else begin
$display("*** Incorrect data: 0x%01x captured by the dut Should be: 0x%01x.",
dut.core.rxd_byte_reg, data);
error_ctr = error_ctr + 1;
if (!invalid_stop_bit) begin // Valid stop bit
if (dut.core.rxd_byte_reg == data & dut.core.erx_ctrl_reg == 0 ) begin
// Data OK, ctrl state idle OK.
$display("*** Correct data: 0x%01x captured by the dut.", dut.core.rxd_byte_reg);
$display("*** Correct state after transmission: 0x%01x (IDLE) .", dut.core.erx_ctrl_reg);
end
else begin
$display("*** Incorrect:");
$display("*** Data: 0x%01x captured by the dut. Expected: 0x%01x.",dut.core.rxd_byte_reg, data);
$display("*** State after transmission: 0x%01x.", dut.core.erx_ctrl_reg);
error_ctr = error_ctr + 1;
end
end else begin
if ( dut.core.erx_ctrl_reg == 5) begin
$display("*** Correct state after transmission: 0x%01x (ERR).", dut.core.erx_ctrl_reg);
end else begin
$display("*** Incorrect state: 0x%01x. Expected: 0x%01x.", dut.core.erx_ctrl_reg, 5);
error_ctr = error_ctr + 1;
end
end
// Reset to a valid rx line
tb_rxd = 1;
#(CLK_PERIOD * dut.DEFAULT_BIT_RATE);
end
endtask // check_transmit
//----------------------------------------------------------------
// test_transmit
//
@ -299,14 +326,71 @@ module tb_uart ();
//----------------------------------------------------------------
task test_transmit;
begin
check_transmit(8'h55);
check_transmit(8'h42);
check_transmit(8'hde);
check_transmit(8'had);
check_transmit(8'h55, 0);
check_transmit(8'h42, 0);
check_transmit(8'hde, 0);
check_transmit(8'h55, 1);
check_transmit(8'had, 0);
end
endtask // test_transmit
//----------------------------------------------------------------
// send_framing_error
//
// Sets the rx line low, and clocks an entire frame, checks the
// UARTs core ctrl state. Sets rx line to idle again, and checks
// that the core returns to idle state.
//----------------------------------------------------------------
task send_framing_error();
integer i;
begin
tc_ctr = tc_ctr + 1;
$display("*** Simulating a constant low rx-line.");
tb_rxd = 0;
// Clock start bit
#(CLK_PERIOD * dut.DEFAULT_BIT_RATE);
// Clock data bits
for (i = 0; i < 8; i = i + 1) begin
tb_rxd = 0;
#(CLK_PERIOD * dut.DEFAULT_BIT_RATE);
end
// Clock stop bit
#(CLK_PERIOD * dut.DEFAULT_BIT_RATE);
// Clock extra to be outside of frame
#(CLK_PERIOD * dut.DEFAULT_BIT_RATE * 3);
if ( dut.core.erx_ctrl_reg == 5) begin
$display("*** Correct state after frame: 0x%01x (ERR).", dut.core.erx_ctrl_reg);
end
else begin
$display("*** Incorrect state: 0x%01x. Expected: 0x%01x.", dut.core.erx_ctrl_reg, 5);
error_ctr = error_ctr + 1;
end
$display("*** Simulate rx-line return to a valid idle state.");
tb_rxd = 1;
#(CLK_PERIOD * dut.DEFAULT_BIT_RATE);
if ( dut.core.erx_ctrl_reg == 0) begin
$display("*** Correct state after rx line returns to valid: 0x%01x (IDLE).", dut.core.erx_ctrl_reg);
end
else begin
$display("*** Incorrect state: 0x%01x. Expected: 0x%01x.", dut.core.erx_ctrl_reg, 0);
error_ctr = error_ctr + 1;
end
end
endtask
//----------------------------------------------------------------
// display_test_result()
//
@ -355,6 +439,8 @@ module tb_uart ();
test_transmit();
send_framing_error();
display_test_result();
$display("*** Simulation done.");
exit_with_error_code();

View file

@ -6,8 +6,8 @@
#
#
# Author: Joachim Strombergson
# Copyright (C) 2022 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#===================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -7,8 +7,8 @@
//
//
// Author: Claire Xenia Wolf
// Copyright (C) 2023 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
//
//======================================================================

View file

@ -6,8 +6,8 @@
#
#
# Author: Joachim Strombergson
# Copyright (C) 2022 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#===================================================================

View file

@ -6,8 +6,8 @@
# Tillitis MTA1_USB_DEV board.
#
#
# Copyright (C) 2022 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#=======================================================================

View file

@ -6,8 +6,8 @@
# on the tk1 board with the CH552 MCU used as a USB-serial chip.
#
#
# Copyright (C) 2022 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
#
#=======================================================================

View file

@ -1,2 +1,2 @@
00010203
073570c0
04050607

View file

@ -1 +1 @@
e72557c38bee1e16114f550b16fc04412bfba09274d7b1fe971ab6b2ef4f06421d976276175ea4df3b7d590599eb052b85a812b689d728be5031ae412b2f8d24 firmware.bin
3962830ae67c08f4e8b6e077c84e2de40b63703a5e1fffe29243ee2a5958d3c9ac992e7b88a2154639ae10db369161cbc27a150b450f047fbcb866b40d8661c9 firmware.bin

View file

@ -65,10 +65,11 @@ The different endpoints:
| *Name* | *Value* | *Comment* |
|--------|---------|----------------------------------------------------------------------|
| DEBUG | 0x20 | A USB HID special debug pipe. Useful for debug prints. |
| CH552 | 0x10 | USB controller control |
| CDC | 0x40 | USB CDC-ACM, a serial port on the client. |
| FIDO | 0x80 | A USB FIDO security token device, useful for FIDO-type applications. |
| CH552 | 0x04 | USB controller control |
| CDC | 0x08 | USB CDC-ACM, a serial port on the client. |
| FIDO | 0x10 | A USB FIDO security token device, useful for FIDO-type applications. |
| CCID | 0x20 | USB CCID, a port for emulating a smart card |
| DEBUG | 0x40 | A USB HID special debug pipe. Useful for debug prints. |
You can turn on and off different endpoints dynamically by sending
commands to the `CH552` control endpoint. When the TKey starts only
@ -162,6 +163,7 @@ stateDiagram-v2
S0 --> S1
S0 --> S4: Default
S0 --> S3
S0 --> SE: Unknown reset type
S1 --> S1: Other commands
S1 --> S2: LOAD_APP
@ -190,8 +192,8 @@ States:
- *LOADING*: Expecting application data from client. Allows only the
command `LOAD_APP_DATA` to continue loading the device app.
- *LOAD_FLASH*: Loading an app from flash. Allows no commands.
- *LOAD_FLASH_MGMT*: Loading and verifyiing a device app from flash.
Allows no commands.
- *LOAD_FLASH_MGMT*: Loading an app from flash and registering it as a
prospective managment app. Allows no commands.
- *START*: Computes CDI. Possibly verifies app. Starts the
application. Does not return to firmware. Allows no commands.
- *FAIL* - Halts CPU. Allows no commands.
@ -206,6 +208,7 @@ Allowed data in state *INITIAL*:
| `FLASH1_VER` | *LOAD_FLASH* |
| `CLIENT` | *WAITCOMMAND* |
| `CLIENT_VER` | *WAITCOMMAND* |
| unknown | *FAIL* |
I/O in state *LOAD_FLASH*:
@ -219,15 +222,16 @@ I/O in state *LOAD_FLASH_MGMT*:
|--------------------|--------------|
| Last app data read | *START* |
Commands in state `waitcommand`:
Commands in state *WAITCOMMAND*:
| *command* | *next state* |
|-----------------------|--------------|
| `FW_CMD_NAME_VERSION` | unchanged |
| `FW_CMD_GET_UDI` | unchanged |
| `FW_CMD_LOAD_APP` | *LOADING* |
| *command* | *next state* |
|-----------------------|--------------------------------------------|
| `FW_CMD_NAME_VERSION` | unchanged |
| `FW_CMD_GET_UDI` | unchanged |
| `FW_CMD_LOAD_APP` | *LOADING* or unchanged on invalid app size |
| | |
Commands in state `loading`:
Commands in state *LOADING*:
| *command* | *next state* |
|------------------------|------------------------------------|
@ -244,17 +248,23 @@ Plain text explanation of the states:
- *INITIAL*: Start here. Check the `FW_RAM` for the `resetinfo` type
for what to do next.
For all types which begins with `FLASH_*`, set next state to
*LOAD_FLASH*, otherwise set next state to *WAITCOMMAND*.
For type `FLASH0` transition to *LOAD_FLASH_MGMT* because the app in
slot 0 is considered a special management app. For all other types
beginning with `FLASH*` transition to *LOAD_FLASH* to load an
ordinary app from flash.
For type `CLIENT*` transitionto *WAITCOMMAND* to expect a device app
from the client.
If type is unknown, error out.
- *LOAD_FLASH*: Load device app from flash into RAM, app slot taken
from context. Compute a BLAKE2s digest over the entire app.
Transition to *START*.
- *LOAD_FLASH_MGMT*: Load device app from flash into RAM, app slot
alway 0. Compute a BLAKE2s digest over the entire app. Register the
app as a prospective management app if it later goes through
verification. Transition to *START*.
always 0. Compute a BLAKE2s digest over the entire app. Register the
app as a prospective management app. Transition to *START*.
- *WAITCOMMAND*: Wait for commands from the client. Transition to
*LOADING* on `LOAD_APP` command, which also sets the size of the
@ -265,7 +275,8 @@ Plain text explanation of the states:
- *START*: Compute the Compound Device Identifier (CDI). If we have a
registered verification digest, verify that the app we are about to
start is indeed the correct app.
start is indeed the correct app. This also means that a prospective
management app is now verified.
Clean up firmware data structures, enable the system calls, and
start the app, which ends the firmware state machine. Hardware
@ -288,29 +299,38 @@ state.
### Golden path from start to default app
Firmware loads the device application at the start of RAM
Firmware will load the device application at the start of RAM
(`0x4000_0000`) from either flash or from the client through the UART.
Firmware uses a part of the FW\_RAM for its own stack.
Firmware is using a part of the FW\_RAM for its own stack.
When reset is released, the CPU starts executing the firmware. It
begins in `start.S` by clearing all CPU registers, clears all FW\_RAM,
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.
except the part reserved for the resetinfo area, 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 fills the entire RAM with pseudo random data
and setting up the RAM address and data hardware scrambling with
values from the True Random Number Generator (TRNG).
1. Check the special resetinfo area in FW\_RAM for reset type. Type
Firmware then proceeds to:
1. Read the partition table from flash and store in FW\_RAM.
2. Reset the CH552 USB controller to a known state, only allowing the
CDC USB endpoint and the internal command channel between the CPU
and the CH552.
3. Check the special resetinfo area in FW\_RAM for reset type. Type
zero means default behaviour, load from flash app slot 0, expecting
the app there to have a specific hardcoded BLAKE2s digest.
2. Load app data from flash slot 0 into RAM.
4. Load app data from flash slot 0 into RAM.
3. Compute a BLAKE2s digest of the loaded app.
5. Compute a BLAKE2s digest of the loaded app.
4. Compare the computed digest against the allowed app digest
6. Compare the computed digest against the allowed app digest
hardcoded in the firmware. If it's not equal, halt CPU.
7. [Start the device app](#start-the-device-app).
@ -371,9 +391,9 @@ Such a verified boot loader app:
- Can be specifically trusted by firmware to be able to do filesystem
management to be able to update an app slot on flash. Add the app's
digest to `allowed_app_digest` in `mgmt_app.c` to allow it to allow
it to use `PRELOAD_DELETE`, `PRELOAD_STORE`, and
`PRELOAD_STORE_FIN`.
digest to `allowed_app_digest` in `mgmt_app.c` to allow it to use
`PRELOAD_DELETE`, `PRELOAD_STORE`, `PRELOAD_STORE_FIN`, and
`PRELOAD_GET_DIGSIG`.
It works like this:
@ -413,7 +433,7 @@ The loader shares the secret with the next app by putting it in the
part of `resetinfo` that is reserved for inter-app communication.
The next app can now use the secret as a seed for it's own key
material. Depending on the app's behaviour and the numer of keys it
material. Depending on the app's behaviour and the number of keys it
needs it can derive more keys, for instance by having nonces stored on
its flash area and doing:
@ -533,8 +553,9 @@ struct reset {
};
struct reset rst;
uint32_t len; // Length of data in next_app_data.
syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0);
syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, len, 0);
```
Resets the TKey. Does not return.
@ -543,7 +564,7 @@ You can pass data to the firmware about the reset type `type` and a
digest that the next app must have. You can also leave some data to
the next app in the chain in `next_app_data`.
The types of the reset are defined in `resetinfo.h`:
The types of reset are defined in `reset.h`:
| *Name* | *Comment* |
|--------------------|------------------------------------------------|
@ -577,12 +598,15 @@ success.
uint32_t offset = 0;
uint8_t buf[17];
TK1_SYSCALL_WRITE_DATA, offset, (uint32_t)buf, sizeof(buf))
syscall(TK1_SYSCALL_WRITE_DATA, offset, (uint32_t)buf, sizeof(buf))
```
Write data in `buf` to the app's flash area at byte `offset` within
the area. Returns 0 on success.
At most 4096 bytes can be written at once and `offset` must be a
multiple of 4096 bytes.
#### `READ_DATA`
```
@ -594,6 +618,20 @@ syscall(TK1_SYSCALL_READ_DATA, offset, (uint32_t)buf, sizeof(buf);
Read into `buf` at byte `offset` from the app's flash area.
#### `ERASE_DATA`
```
uint32_t offset = 0;
uint32_t size = 4096;
syscall(TK1_SYSCALL_ERASE_DATA, offset, size, 0);
```
Erase `size` bytes from `offset` within the area. Returns 0 on
success.
Both `size` and `offset` must be a multiple of 4096 bytes.
#### `PRELOAD_DELETE`
```
@ -615,9 +653,14 @@ syscall(TK1_SYSCALL_PRELOAD_STORE, offset, (uint32_t)appbinary,
```
Store an app, or possible just a block of an app, from the `appbinary`
buffer in flash slot 1 at byte `offset` If you can't find your entire
app in the buffer, call `PRELOAD_STORE` many times as you receive the
binary from the client. Returns 0 on success.
buffer in flash slot 1 at byte `offset`.
If you can't fit your entire app in the buffer, call `PRELOAD_STORE`
many times as you receive the binary from the client. Returns 0 on
success.
At most 4096 bytes can be written at once and `offset` must be a
multiple of 4096 bytes.
Only available for the verified management app.
@ -636,7 +679,8 @@ Finalize storing of an app where the complete binary size is
`app_size` in flash slot 1. Returns 0 on success. Only available for
the verified management app.
Compute the `app_digest` with BLAKE2s over the entire binary.
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`.
@ -693,6 +737,9 @@ functions. Note that these functions are only usable in QEMU and that
you might need to `make clean` before building, if you have already
built before.
To build a flash image file suitable for use with qemu, use the
`tools/tkeyimage` program. See its documentation.
If you want debug prints to show up on the special TKey HID debug
endpoint instead, define `-DTKEY_DEBUG`. This might mean you can't fit
the firmware in the ROM space available, however. You will get a
@ -714,44 +761,6 @@ Most of the utility functions that the firmware use lives in
but we have vendored it in for firmware use in `../tkey-libs`. See top
README for how to update.
### Preparing the filesystem
The TKey supports a simple filesystem. This filesystem must be
initiated before starting for the first time. You need a [TKey
Programmer Board](https://shop.tillitis.se/products/tkey-dev-kit) for
this part.
1. Choose your pre-loaded app. You /must/ have a pre-loaded app, for
example `testloadapp`. Build it with the OCI image we use. The
binary needs to produce the BLAKE2s digest in `allowed_app_digest`
`tk1/mgmt_app.c`.
2. Write the filesystem to flash:
```
$ cd ../tools
$ ./load_preloaded_app.sh 0 ../fw/testloadapp/testloadapp.bin
```
If you want to use a different pre-loaded app you have to
1. Check the BLAKE2s digest of the app. You can use `tools/b2s` to
compute it.
2. Update the `allowed_app_digest` in `tk1/mgmt_app.c`.
3. Create a new `default_partition.bin` using the
`tools/partition_table`, typically:
```
$ partition_table -app0 path/to/your/app.bin -o default_partition.bin
```
4. Flash the filesystem image:
```
$ ./load_preloaded_app.sh 0 path/to/your/app.bin
```
### Test firmware
@ -768,19 +777,61 @@ ordinary `application_fpga/Makefile` to be able to fit in ROM.
### Test apps
There are a couple of test apps. All of them are controlled through
the USB CDC, typically by running picocom or similar terminal program,
like:
There are a couple of test apps, see `../apps`.
## Filesystem
The TKey supports a simple filesystem.
The `tkeyimage` tool is used to parse or generate partition table or
entire filesystem images for the TKey.
The fileystem layout looks like this:
| **name** | **size** | **start address** | **comment** |
|-------------|----------|-------------------|---------------------------|
| Bitstream | 128 kiB | 0x00 | The FPGA bitstream |
| Partition | 64 kiB | 0x20000 | Partition table |
| Slot 0 | 128 kiB | 0x30000 | 1st pre-loaded app |
| Slot 1 | 128 kiB | 0x50000 | 2nd pre-loaded app |
| Storage 0 | 128 kiB | 0x70000 | Storage for app |
| Storage 1 | 128 kiB | 0x90000 | Storage for app |
| Storage 2 | 128 kiB | 0xB0000 | Storage for app |
| Storage 3 | 128 kiB | 0xD0000 | Storage for app |
| Partition 2 | 64 kiB | 0xf0000 | Backup of parititon table |
The partition table is made up of:
| **name** | **size** |
|-----------|-----------------------------------------|
| Version | 1 B |
| App 0 | 4 B length, 32 B digest, 64 B signature |
| App 1 | 4 B length, 32 B digest, 64 B signature |
| Storage 0 | 1 B status, 16 B nonce, 16 B auth tag |
| Storage 1 | 1 B status, 16 B nonce, 16 B auth tag |
| Storage 2 | 1 B status, 16 B nonce, 16 B auth tag |
| Storage 3 | 1 B status, 16 B nonce, 16 B auth tag |
| Checksum | 32 B |
- Digest is a BLAKE2s hash digest of the app.
- Signature is an Ed25519 signature of the above digest.
- Checksum is a BLAKE2s hash digest of everything that came before.
Usual to detect broken flash and a signal to use the backup copy.
The digest and signature are reported from the `PRELOAD_GET_DIGSIG`
syscall as a part of chaining of apps. See Management app, chaining
apps and verified boot.
The storage status field is 0 if not allocated by an app and 1 if
allocated.
The storage auth tag is a way of controlling if a a device app can
access a storage area. It's computed with the 16 byte version of the
BLAKE2s hash function like this:
```
$ picocom /dev/ttyACM1
digest = BLAKE2s_16(CDI, nonce)
```
or similar.
- `fw/testapp`: Runs through a couple of tests that are now impossible
to do in the `testfw`.
- `fw/reset_test`: Interactively test different reset scenarios.
- `fw/testloadapp`: Interactively test management app things like
installing an app (hardcoded for a small happy blinking app, see
`blink.h` for the entire binary!) and to test verified boot.
The auth tag is filled in when a device app first allocates an area.
It is then checked on all calls to access the app storage area.

View file

@ -1,75 +0,0 @@
P := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
LIBDIR ?= ../../tkey-libs
OBJCOPY ?= llvm-objcopy
CC = clang
CFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mcmodel=medany \
-static \
-std=gnu99 \
-O2 \
-ffast-math \
-fno-common \
-fno-builtin-printf \
-fno-builtin-putchar \
-fno-builtin-memcpy \
-nostdlib \
-mno-relax \
-Wall \
-Wpedantic \
-Wno-language-extension-token \
-Werror \
-flto \
-g \
-I $(LIBDIR)/include \
-I $(LIBDIR) \
-DTKEY_DEBUG
AS = clang
ASFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mno-relax
LDFLAGS = \
-T $(P)/app.lds \
-L $(LIBDIR) -lcommon
.PHONY: all
all: reset_test.bin
# Turn elf into bin for device
%.bin: %.elf
$(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $^ $@
chmod a-x $@
.PHONY: tkey-libs
tkey-libs:
make -C $(LIBDIR)
RESET_TEST_FMTFILES = *.[ch]
RESET_TEST_OBJS = \
$(P)/main.o \
$(P)/crt0.o \
$(P)/syscall.o
reset_test.elf: tkey-libs $(RESET_TEST_OBJS)
$(CC) $(CFLAGS) $(RESET_TEST_OBJS) $(LDFLAGS) -o $@
.PHONY: fmt
fmt:
clang-format --dry-run --ferror-limit=0 $(RESET_TEST_FMTFILES)
clang-format --verbose -i $(RESET_TEST_FMTFILES)
.PHONY: checkfmt
checkfmt:
clang-format --dry-run --ferror-limit=0 --Werror $(RESET_TEST_FMTFILES)
.PHONY: clean
clean:
rm -f reset_test.bin reset_test.elf $(RESET_TEST_OBJS)

View file

@ -1,64 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
* SPDX-License-Identifier: BSD-2-Clause
*/
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
MEMORY
{
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */
}
SECTIONS
{
.text.init :
{
*(.text.init)
} >RAM
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.srodata) /* .rodata sections (constants, strings, etc.) */
*(.srodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
_etext = .;
_sidata = _etext;
} >RAM
.data : AT (_etext)
{
. = ALIGN(4);
_sdata = .;
. = ALIGN(4);
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.sdata) /* .sdata sections */
*(.sdata*) /* .sdata* sections */
. = ALIGN(4);
_edata = .;
} >RAM
/* Uninitialized data section */
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss*)
*(.sbss)
*(.sbss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >RAM
/* libcrt0/crt0.S inits stack to start just below end of RAM */
}

View file

@ -1,53 +0,0 @@
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
.section ".text.init"
.global _start
_start:
li x1, 0
li x2, 0
li x3, 0
li x4, 0
li x5, 0
li x6, 0
li x7, 0
li x8, 0
li x9, 0
li x10,0
li x11,0
li x12,0
li x13,0
li x14,0
li x15,0
li x16,0
li x17,0
li x18,0
li x19,0
li x20,0
li x21,0
li x22,0
li x23,0
li x24,0
li x25,0
li x26,0
li x27,0
li x28,0
li x29,0
li x30,0
li x31,0
/* init stack below 0x40020000 (TK1_RAM_BASE+TK1_RAM_SIZE) */
li sp, 0x4001fff0
/* zero-init bss section */
la a0, _sbss
la a1, _ebss
bge a0, a1, end_init_bss
loop_init_bss:
sw zero, 0(a0)
addi a0, a0, 4
blt a0, a1, loop_init_bss
end_init_bss:
call main

View file

@ -1,74 +0,0 @@
P := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
LIBDIR ?= ../../tkey-libs
OBJCOPY ?= llvm-objcopy
CC = clang
CFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mcmodel=medany \
-static \
-std=gnu99 \
-O2 \
-ffast-math \
-fno-common \
-fno-builtin-printf \
-fno-builtin-putchar \
-fno-builtin-memcpy \
-nostdlib \
-mno-relax \
-Wall \
-Wpedantic \
-Wno-language-extension-token \
-Werror \
-flto \
-g \
-I $(LIBDIR)/include \
-I $(LIBDIR)
AS = clang
ASFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mno-relax
LDFLAGS = \
-T $(P)/app.lds \
-L $(LIBDIR) -lcommon
.PHONY: all
all: testapp.bin
# Turn elf into bin for device
%.bin: %.elf
$(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $^ $@
chmod a-x $@
.PHONY: tkey-libs
tkey-libs:
make -C $(LIBDIR)
TESTAPP_FMTFILES = *.[ch]
TESTAPP_OBJS = \
$(P)/main.o \
$(P)/crt0.o \
$(P)/syscall.o
testapp.elf: tkey-libs $(TESTAPP_OBJS)
$(CC) $(CFLAGS) $(TESTAPP_OBJS) $(LDFLAGS) -o $@
.PHONY: fmt
fmt:
clang-format --dry-run --ferror-limit=0 $(TESTAPP_FMTFILES)
clang-format --verbose -i $(TESTAPP_FMTFILES)
.PHONY: checkfmt
checkfmt:
clang-format --dry-run --ferror-limit=0 --Werror $(TESTAPP_FMTFILES)
.PHONY: clean
clean:
rm -f testapp.bin testapp.elf $(TESTAPP_OBJS)

View file

@ -1,64 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
* SPDX-License-Identifier: BSD-2-Clause
*/
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
MEMORY
{
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */
}
SECTIONS
{
.text.init :
{
*(.text.init)
} >RAM
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.srodata) /* .rodata sections (constants, strings, etc.) */
*(.srodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
_etext = .;
_sidata = _etext;
} >RAM
.data : AT (_etext)
{
. = ALIGN(4);
_sdata = .;
. = ALIGN(4);
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.sdata) /* .sdata sections */
*(.sdata*) /* .sdata* sections */
. = ALIGN(4);
_edata = .;
} >RAM
/* Uninitialized data section */
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss*)
*(.sbss)
*(.sbss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >RAM
/* libcrt0/crt0.S inits stack to start just below end of RAM */
}

View file

@ -1,53 +0,0 @@
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
.section ".text.init"
.global _start
_start:
li x1, 0
li x2, 0
li x3, 0
li x4, 0
li x5, 0
li x6, 0
li x7, 0
li x8, 0
li x9, 0
li x10,0
li x11,0
li x12,0
li x13,0
li x14,0
li x15,0
li x16,0
li x17,0
li x18,0
li x19,0
li x20,0
li x21,0
li x22,0
li x23,0
li x24,0
li x25,0
li x26,0
li x27,0
li x28,0
li x29,0
li x30,0
li x31,0
/* init stack below 0x40020000 (TK1_RAM_BASE+TK1_RAM_SIZE) */
li sp, 0x4001fff0
/* zero-init bss section */
la a0, _sbss
la a1, _ebss
bge a0, a1, end_init_bss
loop_init_bss:
sw zero, 0(a0)
addi a0, a0, 4
blt a0, a1, loop_init_bss
end_init_bss:
call main

View file

@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
# Uses ../.clang-format
FMTFILES=*.[ch]
.PHONY: fmt

View file

@ -1,7 +1,5 @@
/*
* Copyright (C) 2022, 2023 - Tillitis AB
* SPDX-License-Identifier: GPL-2.0-only
*/
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stddef.h>
#include <stdint.h>

View file

@ -1,7 +1,5 @@
/*
* Copyright (C) 2022, 2023 - Tillitis AB
* SPDX-License-Identifier: GPL-2.0-only
*/
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
.section ".text.init"
.globl _start
@ -38,7 +36,7 @@ _start:
li x30,0
li x31,0
/* Clear all RAM */
// Clear all RAM
li a0, 0x40000000 // TK1_RAM_BASE
li a1, 0x40020000 // TK1_RAM_BASE + TK1_RAM_SIZE
clear:
@ -46,9 +44,9 @@ clear:
addi a0, a0, 4
blt a0, a1, clear
/*
* For testfw we init stack at top of RAM
*/
// NOTE WELL
// For testfw we init stack at top of RAM
//
li sp, 0x40020000 // TK1_RAM_BASE + TK1_RAM_SIZE
call main

View file

@ -1,73 +0,0 @@
P := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
LIBDIR ?= ../../tkey-libs
OBJCOPY ?= llvm-objcopy
CC = clang
CFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mcmodel=medany \
-static \
-std=gnu99 \
-Os \
-ffast-math \
-fno-common \
-fno-builtin-printf \
-fno-builtin-putchar \
-fno-builtin-memcpy \
-nostdlib \
-mno-relax \
-Wall \
-Wpedantic \
-Wno-language-extension-token \
-Werror \
-flto \
-g \
-I $(LIBDIR)/include \
-I $(LIBDIR)
AS = clang
ASFLAGS = \
-target riscv32-unknown-none-elf \
-march=rv32iczmmul \
-mabi=ilp32 \
-mno-relax
LDFLAGS = \
-T $(LIBDIR)/app.lds \
-L $(LIBDIR) -lcrt0 -lcommon -lmonocypher -lblake2s
.PHONY: all
all: testloadapp.bin
# Turn elf into bin for device
%.bin: %.elf
$(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $^ $@
chmod a-x $@
.PHONY: tkey-libs
tkey-libs:
make -C $(LIBDIR)
TESTLOADAPP_FMTFILES = *.[ch]
TESTLOADAPP_OBJS = \
$(P)/main.o \
../testapp/syscall.o \
testloadapp.elf: tkey-libs $(TESTLOADAPP_OBJS)
$(CC) $(CFLAGS) $(TESTLOADAPP_OBJS) $(LDFLAGS) -o $@
.PHONY: fmt
fmt:
clang-format --dry-run --ferror-limit=0 $(TESTLOADAPP_FMTFILES)
clang-format --verbose -i $(TESTLOADAPP_FMTFILES)
.PHONY: checkfmt
checkfmt:
clang-format --dry-run --ferror-limit=0 --Werror $(TESTLOADAPP_FMTFILES)
.PHONY: clean
clean:
rm -f testloadapp.bin testloadapp.elf $(TESTLOADAPP_OBJS)

View file

@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
# SPDX-License-Identifier: BSD-2-Clause
# Uses ../.clang-format
FMTFILES=*.[ch]

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stdbool.h>
#include <stdint.h>
@ -14,8 +14,8 @@
static volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
/* Calculates the authentication digest based on a supplied nonce and the CDI.
* Requires that the CDI is already calculated and stored */
// Calculates the authentication digest based on a supplied nonce and
// the CDI. Requires that the CDI is already calculated and stored
static void calculate_auth_digest(uint8_t *nonce, uint8_t *auth_digest)
{
assert(nonce != NULL);
@ -31,7 +31,7 @@ static void calculate_auth_digest(uint8_t *nonce, uint8_t *auth_digest)
blake2s_final(&ctx, auth_digest);
}
/* Generates a 16 byte nonce */
// Generates a 16 byte nonce
static void generate_nonce(uint32_t *nonce)
{
assert(nonce != NULL);
@ -41,8 +41,9 @@ static void generate_nonce(uint32_t *nonce)
}
return;
}
/* Returns the authentication digest and random nonce. Requires that the CDI is
* already calculated and stored */
// Returns the authentication digest and random nonce. Requires that
// the CDI is already calculated and stored
void auth_app_create(struct auth_metadata *auth_table)
{
assert(auth_table != NULL);

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#ifndef AUTH_APP_H
#define AUTH_APP_H

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2022, 2023 - Tillitis AB
* SPDX-License-Identifier: GPL-2.0-only
* SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
* SPDX-License-Identifier: BSD-2-Clause
*/
OUTPUT_ARCH("riscv")

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stdbool.h>
#include <stddef.h>
@ -10,36 +10,12 @@
#include "flash.h"
#include "spi.h"
// clang-format off
static volatile uint32_t *timer = (volatile uint32_t *)TK1_MMIO_TIMER_TIMER;
static volatile uint32_t *timer_prescaler = (volatile uint32_t *)TK1_MMIO_TIMER_PRESCALER;
static volatile uint32_t *timer_status = (volatile uint32_t *)TK1_MMIO_TIMER_STATUS;
static volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
// clang-format on
// CPU clock frequency in Hz
#define CPUFREQ 21000000
#define PAGE_SIZE 256
static bool flash_is_busy(void);
static void flash_wait_busy(void);
static void flash_write_enable(void);
static void delay(int timeout_ms)
{
// Tick once every centisecond
*timer_prescaler = CPUFREQ / 100;
*timer = timeout_ms / 10;
*timer_ctrl |= (1 << TK1_MMIO_TIMER_CTRL_START_BIT);
while (*timer_status != 0) {
}
// Stop timer
*timer_ctrl |= (1 << TK1_MMIO_TIMER_CTRL_STOP_BIT);
}
static bool flash_is_busy(void)
{
uint8_t tx_buf = READ_STATUS_REG_1;
@ -58,9 +34,8 @@ static bool flash_is_busy(void)
// Blocking until !busy
static void flash_wait_busy(void)
{
while (flash_is_busy()) {
delay(10);
}
while (flash_is_busy())
;
}
static void flash_write_enable(void)
@ -201,7 +176,11 @@ int flash_write_data(uint32_t address, uint8_t *data, size_t size)
return -1;
}
if (size <= 0 || size > 4096) {
if (size <= 0) {
return -1;
}
if (address % 256 != 0) {
return -1;
}
@ -209,6 +188,12 @@ int flash_write_data(uint32_t address, uint8_t *data, size_t size)
uint8_t *p_data = data;
size_t n_bytes = 0;
// Page Program allows 1-256 bytes of a page to be written. A page is
// 256 bytes. Behavior when writing past the end of a page is device
// specific.
//
// We set the address LSByte to 0 and only write 256 bytes or less in
// each transfer.
uint8_t tx_buf[4] = {
PAGE_PROGRAM, /* tx_buf[0] */
(address >> ADDR_BYTE_3_BIT) & 0xFF, /* tx_buf[1] */

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#ifndef TKEY_FLASH_H
#define TKEY_FLASH_H

View file

@ -1,7 +1,5 @@
/*
* Copyright (C) 2022, 2023 - Tillitis AB
* SPDX-License-Identifier: GPL-2.0-only
*/
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <blake2s/blake2s.h>
#include <stdbool.h>
@ -17,7 +15,7 @@
#include "partition_table.h"
#include "preload_app.h"
#include "proto.h"
#include "resetinfo.h"
#include "reset.h"
#include "state.h"
#include "syscall_enable.h"
@ -38,7 +36,7 @@ static volatile uint32_t *timer_status = (volatile uint32_t *)TK1_MMIO_TIMER
static volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
static volatile uint32_t *ram_addr_rand = (volatile uint32_t *)TK1_MMIO_TK1_RAM_ADDR_RAND;
static volatile uint32_t *ram_data_rand = (volatile uint32_t *)TK1_MMIO_TK1_RAM_DATA_RAND;
static volatile struct reset *resetinfo = (volatile struct reset *)TK1_MMIO_RESETINFO_BASE;
static volatile struct reset *resetinfo = (volatile struct reset *)TK1_MMIO_RESETINFO_BASE;
// clang-format on
struct partition_table_storage part_table_storage;
@ -252,6 +250,8 @@ static enum state initial_commands(const struct frame_header *hdr,
ctx->left = *app_size;
led_set(LED_BLACK);
state = FW_STATE_LOADING;
break;
}
@ -444,7 +444,19 @@ static enum state start_where(struct context *ctx)
{
assert(ctx != NULL);
// Where do we start? Read resetinfo 'startfrom'
debug_puts("resetinfo->type: ");
debug_putinthex(resetinfo->type);
debug_lf();
debug_puts(" ->app_digest: \n");
debug_hexdump((void *)resetinfo->app_digest, RESET_DIGEST_SIZE);
debug_lf();
debug_puts(" ->next_app_data: \n");
debug_hexdump((void *)resetinfo->next_app_data, RESET_DATA_SIZE);
debug_lf();
// Where do we start?
switch (resetinfo->type) {
case START_DEFAULT:
// fallthrough
@ -496,8 +508,6 @@ int main(void)
uint8_t cmd[CMDSIZE] = {0};
enum state state = FW_STATE_INITIAL;
led_set(LED_BLUE);
print_hw_version();
/*@-mustfreeonly@*/
@ -511,10 +521,17 @@ int main(void)
scramble_ram();
if (part_table_read(&part_table_storage) != 0) {
// Couldn't read or create partition table
// Couldn't read partition table
debug_puts("Couldn't read partition table\n");
assert(1 == 2);
}
// Reset the USB controller to only enable the USB CDC
// endpoint and the internal command channel.
config_endpoints(IO_CDC | IO_CH552);
led_set(LED_WHITE);
#if defined(SIMULATION)
run(&ctx);
#endif
@ -567,6 +584,7 @@ int main(void)
if (mgmt_app_init(ctx.digest) != 0) {
state = FW_STATE_FAIL;
break;
}
state = FW_STATE_START;
@ -604,7 +622,7 @@ int main(void)
}
/*@ -compdestroy @*/
/* We don't care about memory leaks here. */
// We don't care about memory leaks here.
return (int)0xcafebabe;
}

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stdbool.h>
#include <stdint.h>
@ -10,12 +10,9 @@
// Lock down what app can start from flash slot 0.
//
// To update this, compute the BLAKE2s digest of the app.bin
static const uint8_t allowed_app_digest[32] = {
0xb6, 0x86, 0x1b, 0x26, 0xef, 0x69, 0x77, 0x12, 0xed, 0x6c, 0xca,
0xe8, 0x35, 0xb4, 0x5c, 0x01, 0x07, 0x71, 0xab, 0xce, 0x3f, 0x30,
0x79, 0xda, 0xe6, 0xf9, 0xee, 0x4b, 0xe2, 0x06, 0x95, 0x33,
};
// To update this, compute the BLAKE2s digest of the device app
// binare, see the b2s tool.
#include "mgmt_app_digest.h"
static uint8_t current_app_digest[32];
@ -31,7 +28,7 @@ int mgmt_app_init(uint8_t app_digest[32])
return 0;
}
/* Authenticate an management app */
// Authenticate an management app
bool mgmt_app_authenticate(void)
{
return memeq(current_app_digest, allowed_app_digest, 32) != 0;

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#ifndef MGMT_APP_H
#define MGMT_APP_H

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stdint.h>
#include <tkey/assert.h>
@ -17,22 +17,20 @@ enum part_status part_get_status(void)
return part_status;
}
static void part_digest(struct partition_table *part_table, uint8_t *out_digest,
size_t out_len);
static void part_checksum(struct partition_table *part_table,
uint8_t *out_digest, size_t out_len);
static void part_digest(struct partition_table *part_table, uint8_t *out_digest,
size_t out_len)
// part_digest computes a checksum over the partition table to detect
// flash problems
static void part_checksum(struct partition_table *part_table,
uint8_t *out_digest, size_t out_len)
{
int blake2err = 0;
uint8_t key[16] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
assert(part_table != NULL);
assert(out_digest != NULL);
blake2err = blake2s(out_digest, out_len, key, sizeof(key), part_table,
blake2err = blake2s(out_digest, out_len, NULL, 0, part_table,
sizeof(struct partition_table));
assert(blake2err == 0);
@ -50,7 +48,7 @@ int part_table_read(struct partition_table_storage *storage)
ADDR_PARTITION_TABLE_0,
ADDR_PARTITION_TABLE_1,
};
uint8_t check_digest[PART_DIGEST_SIZE] = {0};
uint8_t check_digest[PART_CHECKSUM_SIZE] = {0};
if (storage == NULL) {
return -1;
@ -64,10 +62,10 @@ int part_table_read(struct partition_table_storage *storage)
sizeof(*storage)) != 0) {
return -1;
}
part_digest(&storage->table, check_digest,
sizeof(check_digest));
part_checksum(&storage->table, check_digest,
sizeof(check_digest));
if (memeq(check_digest, storage->check_digest,
if (memeq(check_digest, storage->checksum,
sizeof(check_digest))) {
if (i == 1) {
part_status = PART_SLOT0_INVALID;
@ -91,8 +89,8 @@ int part_table_write(struct partition_table_storage *storage)
return -1;
}
part_digest(&storage->table, storage->check_digest,
sizeof(storage->check_digest));
part_checksum(&storage->table, storage->checksum,
sizeof(storage->checksum));
for (int i = 0; i < 2; i++) {
flash_sector_erase(offset[i]);

View file

@ -1,30 +1,30 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#ifndef PARTITION_TABLE_H
#define PARTITION_TABLE_H
#include <stdint.h>
/* ---- Flash ---- ---- */
/* name size start addr */
/* ---- ---- ---- */
/* bitstream 128KiB 0x00 */
/* ---- ---- ---- */
/* Partition 64KiB 0x20000 */
/* ---- ---- ---- */
/* Pre load 1 128KiB 0x30000 */
/* Pre load 2 128KiB 0x50000 */
/* ---- ---- ---- */
/* storage 1 128KiB 0x70000 */
/* storage 2 128KiB 0x90000 */
/* storage 3 128KiB 0xB0000 */
/* storage 4 128KiB 0xD0000 */
/* ---- ---- ---- */
/* Partition2 64KiB 0xf0000 */
// ---- Flash ---- ----
// name size start addr
// ---- ---- ----
// bitstream 128KiB 0x00
// ---- ---- ----
// Partition 64KiB 0x20000
// ---- ---- ----
// Pre load 1 128KiB 0x30000
// Pre load 2 128KiB 0x50000
// ---- ---- ----
// storage 1 128KiB 0x70000
// storage 2 128KiB 0x90000
// storage 3 128KiB 0xB0000
// storage 4 128KiB 0xD0000
// ---- ---- ----
// Partition2 64KiB 0xf0000
/* To simplify all blocks are aligned with the 64KiB blocks on the W25Q80DL
* flash. */
// To simplify all blocks are aligned with the 64KiB blocks on the
// W25Q80DL flash.
#define PART_TABLE_VERSION 1
@ -46,30 +46,33 @@
#define SIZE_STORAGE_AREA 0x20000UL // 128KiB
#define N_STORAGE_AREA 4
#define PART_DIGEST_SIZE 16
#define PART_CHECKSUM_SIZE 32
enum part_status {
PART_SLOT0_INVALID = 1,
};
/* Partition Table */
/*- Table header */
/* - 1 bytes Version */
/**/
/*- Pre-loaded device app 1 */
/* - 4 bytes length. */
/* - 32 bytes digest. */
/* - 64 bytes signature. */
/**/
/*- Pre-loaded device app 2 */
/* - 4 bytes length. */
/* - 32 bytes digest. */
/* - 64 bytes signature. */
/**/
/*- Device app storage area */
/* - 1 byte status. */
/* - 16 bytes random nonce. */
/* - 16 bytes authentication tag. */
// Partition Table
// ----------------------------------------------------------------------
// - Table header
// - 1 bytes Version
//
// - Pre-loaded device app 1
// - 4 bytes length.
// - 32 bytes digest.
// - 64 bytes signature.
//
// - Pre-loaded device app 2
// - 4 bytes length.
// - 32 bytes digest.
// - 64 bytes signature.
//
// - Device app storage area
// - 1 byte status.
// - 16 bytes random nonce.
// - 16 bytes authentication tag.
//
// - Checksum over the above
struct auth_metadata {
uint8_t nonce[16];
@ -99,7 +102,7 @@ struct partition_table {
struct partition_table_storage {
struct partition_table table;
uint8_t check_digest[PART_DIGEST_SIZE];
uint8_t checksum[PART_CHECKSUM_SIZE]; // Helps detect flash problems
} __attribute__((packed));
enum part_status part_get_status(void);

View file

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View file

@ -2,6 +2,11 @@
## custom_ops.S
Custom PicoRV32 instructions are located in `custom_ops.S`.
`custom_ops.S` is imported from upstream PicoRV32 commit:
YosysHQ/picorv32@70f3c33
We have imported the custom Custom PicoRV32 instructions in
`custom_ops.S` from https://github.com/YosysHQ/picorv32/ tag v1.0,
commit 6d145b708d5dfa4caa3445bc599927cebc3291d8.
Upstream path is `picorv32/firmware/custom_ops.S`.
The picorv32 firmware is public domain, which we chose to mark as
CC0-1.0.

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Claire Xenia Wolf <claire@yosyshq.com>
// SPDX-License-Identifier: CC0-1.0
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stdbool.h>
#include <stddef.h>
@ -18,58 +18,72 @@ static uint32_t slot_to_start_address(uint8_t slot)
return ADDR_PRE_LOADED_APP_0 + slot * SIZE_PRE_LOADED_APP;
}
/* Loads a preloaded app from flash to app RAM */
// Loads a preloaded app from flash to app RAM
int preload_load(struct partition_table *part_table, uint8_t from_slot)
{
if (part_table == NULL) {
return -5;
return -1;
}
if (from_slot >= N_PRELOADED_APP) {
return -4;
return -1;
}
/*Check for a valid app in flash */
if (part_table->pre_app_data[from_slot].size == 0) {
// Check for a valid app in flash
if (part_table->pre_app_data[from_slot].size == 0 &&
part_table->pre_app_data[from_slot].size <= TK1_APP_MAX_SIZE) {
return -1;
}
uint8_t *loadaddr = (uint8_t *)TK1_RAM_BASE;
/* Read from flash, straight into RAM */
// Read from flash, straight into RAM
int ret = flash_read_data(slot_to_start_address(from_slot), loadaddr,
part_table->pre_app_data[from_slot].size);
return ret;
}
/* Expects to receive chunks of data up to 4096 bytes to store into the
* preloaded area. The offset needs to be kept and updated between each call.
* Once done, call preload_store_finalize() with the last parameters.
* */
// preload_store stores chunks of an app in app slot to_slot. data is a buffer
// of size size to be written at byte offset in the slot. offset needs to be
// kept and updated between each call. offset must be a multiple of 256.
//
// When all data has been written call preload_store_finalize() with the last
// parameters.
//
// Returns 0 on success.
int preload_store(struct partition_table *part_table, uint32_t offset,
uint8_t *data, size_t size, uint8_t to_slot)
{
if (part_table == NULL || data == NULL) {
return -5;
return -1;
}
if (to_slot >= N_PRELOADED_APP) {
return -4;
return -1;
}
/* Check if we are allowed to store */
// Check if we are allowed to store
if (!mgmt_app_authenticate()) {
return -3;
return -1;
}
/* Check for a valid app in flash, bale out if it already exists */
// Check for a valid app in flash, bale out if it already
// exists
if (part_table->pre_app_data[to_slot].size != 0) {
return -1;
}
if ((offset + size) > SIZE_PRE_LOADED_APP || size > 4096) {
/* Writing outside of area */
return -2;
if (offset > SIZE_PRE_LOADED_APP) {
return -1;
}
if (size > SIZE_PRE_LOADED_APP) {
return -1;
}
if ((offset + size) > SIZE_PRE_LOADED_APP) {
// Writing outside of area
return -1;
}
uint32_t address = slot_to_start_address(to_slot) + offset;
@ -87,26 +101,38 @@ int preload_store_finalize(struct partition_table_storage *part_table_storage,
{
struct partition_table *part_table = &part_table_storage->table;
if (part_table == NULL || app_digest == NULL || app_signature == NULL) {
return -5;
if (part_table == NULL) {
return -1;
}
// Allow data to point only to app RAM
if (app_digest < (uint8_t *)TK1_RAM_BASE ||
app_digest >= (uint8_t *)(TK1_RAM_BASE + TK1_RAM_SIZE)) {
return -1;
}
if (app_signature < (uint8_t *)TK1_RAM_BASE ||
app_signature >= (uint8_t *)(TK1_RAM_BASE + TK1_RAM_SIZE)) {
return -1;
}
if (to_slot >= N_PRELOADED_APP) {
return -4;
return -1;
}
/* Check if we are allowed to store */
// Check if we are allowed to store
if (!mgmt_app_authenticate()) {
return -3;
return -1;
}
/* Check for a valid app in flash, bale out if it already exists */
// Check for a valid app in flash, bale out if it already
// exists
if (part_table->pre_app_data[to_slot].size != 0) {
return -1;
}
if (app_size == 0 || app_size > SIZE_PRE_LOADED_APP) {
return -2;
return -1;
}
part_table->pre_app_data[to_slot].size = app_size;
@ -121,7 +147,7 @@ int preload_store_finalize(struct partition_table_storage *part_table_storage,
debug_lf();
if (part_table_write(part_table_storage) != 0) {
return -6;
return -1;
}
return 0;
@ -133,19 +159,19 @@ int preload_delete(struct partition_table_storage *part_table_storage,
struct partition_table *part_table = &part_table_storage->table;
if (part_table_storage == NULL) {
return -5;
return -1;
}
if (slot >= N_PRELOADED_APP) {
return -4;
return -1;
}
/* Check if we are allowed to deleted */
// Check if we are allowed to delete
if (!mgmt_app_authenticate()) {
return -3;
return -1;
}
/*Check for a valid app in flash */
// Check for a valid app in flash
if (part_table->pre_app_data[slot].size == 0) {
// Nothing to do.
return 0;
@ -160,10 +186,10 @@ int preload_delete(struct partition_table_storage *part_table_storage,
sizeof(part_table->pre_app_data[slot].signature));
if (part_table_write(part_table_storage) != 0) {
return -6;
return -1;
}
/* Assumes the area is 64 KiB block aligned */
// Assumes the area is 64 KiB block aligned
flash_block_64_erase(
slot_to_start_address(slot)); // Erase first 64 KB block
flash_block_64_erase(slot_to_start_address(slot) +
@ -177,16 +203,16 @@ int preload_get_digsig(struct partition_table *part_table,
uint8_t slot)
{
if (part_table == NULL || app_digest == NULL || app_signature == NULL) {
return -5;
return -1;
}
if (slot >= N_PRELOADED_APP) {
return -4;
return -1;
}
/* Check if we are allowed to read */
// Check if we are allowed to read
if (!mgmt_app_authenticate()) {
return -3;
return -1;
}
memcpy_s(app_digest, 32, part_table->pre_app_data[slot].digest,

View file

@ -1,5 +1,5 @@
// Copyright (C) 2024 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#ifndef PRELOAD_APP_H
#define PRELOAD_APP_H

View file

@ -1,7 +1,5 @@
/*
* Copyright (C) 2022, 2023 - Tillitis AB
* SPDX-License-Identifier: GPL-2.0-only
*/
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// SPDX-License-Identifier: BSD-2-Clause
#include <stdint.h>
#include <tkey/assert.h>

Some files were not shown because too many files have changed in this diff Show more