mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-03-13 10:36:53 -04:00
fw: Import tkey-libs fw-2
This is an import of the fw-2 tag of tkey-libs. We import the entire tkey-libs repo minus dot files into the tillitis-key1 repo to make it very simple not to make mistakes regarding which firmware tag depends on which tkey-libs tag, especially considering locking down with NVCM. Please see README for information about developing with another tkey-libs or how to import future tkey-libs. Since tkey-libs is now a part of the repo we also add tkey-libs to the clean_fw target.
This commit is contained in:
parent
59b5360bcb
commit
3875508d1f
3
.gitignore
vendored
3
.gitignore
vendored
@ -28,6 +28,9 @@
|
||||
/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
|
||||
synth.json
|
||||
synth.txt
|
||||
synth.v
|
||||
|
33
README.md
33
README.md
@ -70,6 +70,39 @@ Note that the TP1 is only used for provisioning the FPGA bitstream
|
||||
into flash or the FPGA configuration memory. It's not necessary if you
|
||||
just want to develop apps for the TKey.
|
||||
|
||||
We use the tkey-libs libraries used for device app development in the
|
||||
firmware, too:
|
||||
|
||||
https://github.com/tillitis/tkey-libs
|
||||
|
||||
but keep our own copy of it in the repo. See below.
|
||||
|
||||
## Updating and working with tkey-libs
|
||||
|
||||
A copy of [tkey-libs](https://github.com/tillitis/tkey-libs) is kept
|
||||
in `hw/application_fpga/tkey-libs`. This is mostly to avoid the
|
||||
subtleties of Git submodules.
|
||||
|
||||
If you want to change something in tkey-libs, always change in the
|
||||
upstream library at:
|
||||
|
||||
https://github.com/tillitis/tkey-libs
|
||||
|
||||
You can build with an out-of-tree copy if you set `LIBDIR`, for
|
||||
example:
|
||||
|
||||
```
|
||||
make LIBDIR=~/git/tkey-libs firmware.elf
|
||||
```
|
||||
|
||||
When it's time to update the in-tree tkey-lib first tag the upstream
|
||||
repo with an `fw` prefix, like `fw-1` even if it already has an
|
||||
official version tag.
|
||||
|
||||
Easiest is probably to just remove the tkey-libs directory and then
|
||||
git clone the desired tag. Use the entire repo, but remove the .-files
|
||||
like `.git`, `.github`, et cetera.
|
||||
|
||||
## Measured boot
|
||||
|
||||
The key behind guaranteeing security even as a general computer is the
|
||||
|
@ -492,6 +492,7 @@ clean_fw:
|
||||
rm -f testfw.{elf,map,bin,hex}
|
||||
rm -f $(TESTFW_OBJS)
|
||||
rm -f qemu_firmware.elf
|
||||
make -C tkey-libs clean
|
||||
.PHONY: clean_fw
|
||||
|
||||
clean_sim:
|
||||
|
26
hw/application_fpga/tkey-libs/LICENSE
Normal file
26
hw/application_fpga/tkey-libs/LICENSE
Normal file
@ -0,0 +1,26 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
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.
|
24
hw/application_fpga/tkey-libs/LICENSES/BSD-2-Clause.txt
Normal file
24
hw/application_fpga/tkey-libs/LICENSES/BSD-2-Clause.txt
Normal 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
hw/application_fpga/tkey-libs/LICENSES/CC0-1.0.txt
Normal file
121
hw/application_fpga/tkey-libs/LICENSES/CC0-1.0.txt
Normal 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.
|
94
hw/application_fpga/tkey-libs/Makefile
Normal file
94
hw/application_fpga/tkey-libs/Makefile
Normal file
@ -0,0 +1,94 @@
|
||||
OBJCOPY ?= llvm-objcopy
|
||||
|
||||
CC = clang
|
||||
|
||||
INCLUDE=include
|
||||
|
||||
# Set QEMU_DEBUG and TKEY_DEBUG below when compiling tkey-libs if you
|
||||
# want debug prints from tkey-libs functions.
|
||||
#
|
||||
# - QEMU_DEBUG: the debug port on our qemu emulator
|
||||
#
|
||||
# - TKEY_DEBUG: The extra HID endpoint on a real TKey which you can
|
||||
# listen on for debug prints.
|
||||
#
|
||||
# NOTE WELL: If you just want debug prints on either of them in *your
|
||||
# own device app* you just need to include tkey/debug.h and define
|
||||
# either of them. You don't need to recompile tkey-libs.
|
||||
|
||||
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 -nostdlib -mno-relax -flto \
|
||||
-Wall -Werror=implicit-function-declaration \
|
||||
-I $(INCLUDE) -I .
|
||||
|
||||
AS = clang
|
||||
AR = llvm-ar
|
||||
ASFLAGS = -target riscv32-unknown-none-elf -march=rv32iczmmul -mabi=ilp32 \
|
||||
-mcmodel=medany -mno-relax
|
||||
|
||||
LDFLAGS=-T app.lds -L libcommon/ -lcommon -L libcrt0/ -lcrt0
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all: libcrt0.a libcommon.a libmonocypher.a
|
||||
|
||||
IMAGE=ghcr.io/tillitis/tkey-builder:4
|
||||
|
||||
podman:
|
||||
podman run --rm --mount type=bind,source=$(CURDIR),target=/src \
|
||||
-w /src -it $(IMAGE) make -j
|
||||
|
||||
.PHONY: check
|
||||
check:
|
||||
clang-tidy -header-filter=.* -checks=cert-* libcommon/*.c -- $(CFLAGS)
|
||||
|
||||
# C runtime library
|
||||
libcrt0.a: libcrt0/crt0.o
|
||||
$(AR) -qc $@ libcrt0/crt0.o
|
||||
|
||||
# Common C functions
|
||||
LIBOBJS=libcommon/assert.o libcommon/blake2s.o libcommon/led.o libcommon/lib.o \
|
||||
libcommon/proto.o libcommon/touch.o libcommon/io.o
|
||||
|
||||
libcommon.a: $(LIBOBJS)
|
||||
$(AR) -qc $@ $(LIBOBJS)
|
||||
$(LIBOBJS): include/tkey/assert.h include/tkey/blake2s.h include/tkey/led.h \
|
||||
include/tkey/lib.h include/tkey/proto.h include/tkey/tk1_mem.h \
|
||||
include/tkey/touch.h include/tkey/debug.h
|
||||
|
||||
# Monocypher
|
||||
MONOOBJS=monocypher/monocypher.o monocypher/monocypher-ed25519.o
|
||||
libmonocypher.a: $(MONOOBJS)
|
||||
$(AR) -qc $@ $(MONOOBJS)
|
||||
$MONOOBJS: monocypher/monocypher-ed25519.h monocypher/monocypher.h
|
||||
|
||||
LIBS=libcrt0.a libcommon.a
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(LIBS) $(LIBOBJS) libcrt0/crt0.o
|
||||
rm -f libmonocypher.a $(MONOOBJS)
|
||||
|
||||
# Create compile_commands.json for clangd and LSP
|
||||
.PHONY: clangd
|
||||
clangd: compile_commands.json
|
||||
compile_commands.json:
|
||||
$(MAKE) clean
|
||||
bear -- make all
|
||||
|
||||
# Uses ../.clang-format
|
||||
FMTFILES=include/tkey/*.h libcommon/*.c
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||
clang-format --verbose -i $(FMTFILES)
|
||||
.PHONY: checkfmt
|
||||
checkfmt:
|
||||
clang-format --dry-run --ferror-limit=0 --Werror $(FMTFILES)
|
||||
|
||||
.PHONY: update-mem-include
|
||||
update-mem-include:
|
||||
cp -af ../tillitis-key1/hw/application_fpga/fw/tk1_mem.h \
|
||||
include/tkey/tk1_mem.h
|
||||
echo "Remember to update header include guard!"
|
29
hw/application_fpga/tkey-libs/README-DIST.txt
Normal file
29
hw/application_fpga/tkey-libs/README-DIST.txt
Normal file
@ -0,0 +1,29 @@
|
||||
tkey-libs binary distribution
|
||||
|
||||
This is the binary distribution of:
|
||||
|
||||
https://github.com/tillitis/tkey-libs
|
||||
|
||||
Which is an SDK for developing device apps for the Tillitis TKey in C.
|
||||
Please see the TKey Developer Handbook for more:
|
||||
|
||||
https://dev.tillitis.se/
|
||||
|
||||
and the company web site:
|
||||
|
||||
https://tillitis.se/
|
||||
|
||||
You should be able to use this distribution directly in device apps
|
||||
simply by pointing LIBDIR to where you unpacked this archive:
|
||||
|
||||
make LIBDIR=~/Download/tkey-libs
|
||||
|
||||
Copyright Tillitis AB.
|
||||
|
||||
These programs are free software: you can redistribute it and/or
|
||||
modify it under the terms of the BSD-2-Clause license.
|
||||
|
||||
See LICENSE for the full BSD-2-Clause license text.
|
||||
|
||||
Note that Monocypher is Copyright Loup Vaillant and released under CC0
|
||||
1.0 Universal, see monocypher/LICENSE.
|
125
hw/application_fpga/tkey-libs/README.md
Normal file
125
hw/application_fpga/tkey-libs/README.md
Normal file
@ -0,0 +1,125 @@
|
||||
[](https://github.com/tillitis/tkey-libs/actions/workflows/ci.yaml)
|
||||
|
||||
# Device libraries for the Tillitis TKey
|
||||
|
||||
- C runtime: libcrt0.
|
||||
- Common C functions including protocol calls: libcommon.
|
||||
- Cryptographic functions: libmonocypher.
|
||||
Based on monocypher version 4.0.2
|
||||
https://github.com/LoupVaillant/Monocypher
|
||||
|
||||
Release notes in [RELEASE.md](RELEASE.md).
|
||||
|
||||
## Licenses and SPDX tags
|
||||
Unless otherwise noted, the project sources are copyright Tillitis AB,
|
||||
licensed under the terms and conditions of the "BSD-2-Clause" license.
|
||||
See [LICENSE](LICENSE) for the full license text.
|
||||
|
||||
Until Oct 8, 2024, the license was GPL-2.0 Only.
|
||||
|
||||
External source code we have imported are isolated in their own
|
||||
directories. They may be released under other licenses. This is noted
|
||||
with a similar `LICENSE` file in every directory containing imported
|
||||
sources.
|
||||
|
||||
The project uses single-line references to Unique License Identifiers
|
||||
as defined by the Linux Foundation's [SPDX project](https://spdx.org/)
|
||||
on its own source files, but not necessarily imported files. 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/).
|
||||
|
||||
## Hardware support
|
||||
|
||||
### Bellatrix and earlier
|
||||
|
||||
Please note that you need to use `uart_write()` and `uart_read()` for
|
||||
I/O.
|
||||
|
||||
If you want debug prints in QEMU you can still use `write(IO_QEMU,
|
||||
...)`. Avoid using `write()` in other cases.
|
||||
|
||||
## Building
|
||||
In order to build, you must have the `make`, `clang`, `llvm`, and
|
||||
`lld` packages installed.
|
||||
|
||||
Version 15 or higher of LLVM/Clang is necessary for the RV32IC\_Zmmul
|
||||
architecture we are using. For more detailed information on the
|
||||
supported build and development environment, please refer to the
|
||||
[Developer Handbook](https://dev.tillitis.se/).
|
||||
## Building using Podman
|
||||
|
||||
You can also build the libraries with our OCI image
|
||||
`ghcr.io/tillitis/tkey-builder`.
|
||||
|
||||
The easiest way to build this is if you have `make` installed:
|
||||
|
||||
```
|
||||
make podman
|
||||
```
|
||||
|
||||
You can also specify a different image by using
|
||||
`IMAGE=localhost/tkey-builder-local`.
|
||||
|
||||
Or use Podman directly:
|
||||
|
||||
```
|
||||
podman run --rm --mount type=bind,source=.,target=/src -w /src -it ghcr.io/tillitis/tkey-builder:4 make -j
|
||||
```
|
||||
|
||||
## Minimal application build
|
||||
|
||||
You will typically need to link at least the `libcrt0` C runtime
|
||||
otherwise your program won't even reach `main()`.
|
||||
|
||||
We provide a linker script in `apps.lds` which shows the linker the
|
||||
memory layout.
|
||||
|
||||
Minimal compilation would look something like:
|
||||
|
||||
```
|
||||
clang -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 -nostdlib -mno-relax -flto \
|
||||
-Wall -Werror=implicit-function-declaration \
|
||||
-I ../tkey-libs/include \
|
||||
-I ../tkey-libs -c -o foo.o foo.c
|
||||
|
||||
clang -target riscv32-unknown-none-elf -march=rv32iczmmul -mabi=ilp32 \
|
||||
-mcmodel=medany -static -ffast-math -fno-common -nostdlib \
|
||||
-T ../tkey-libs/app.lds \
|
||||
-L ../tkey-libs -lcrt0 \
|
||||
-I ../tkey-libs -o foo.elf foo.o
|
||||
|
||||
```
|
||||
|
||||
## Makefile example
|
||||
|
||||
See `example-app/Makefile` for an example Makefile for a simple device
|
||||
application.
|
||||
|
||||
## Debug output
|
||||
|
||||
If you want to have debug prints in your program you can use the
|
||||
`debug_putchar()`, `debug_puts()`, `debug_putinthex()`,
|
||||
`debug_hexdump()` and friends. See `include/tkey/debug.h` for list of
|
||||
functions.
|
||||
|
||||
These functions will be turned on if you define either of these when
|
||||
compiling your program and linking with `libcommon`:
|
||||
|
||||
- `QEMU_DEBUG`: Uses the special debug port only available in qemu to
|
||||
print to the qemu console.
|
||||
- `TKEY_DEBUG`: Uses the extra HID device.
|
||||
|
||||
Note that if you use `TKEY_DEBUG` you *must* have something listening
|
||||
on the corresponding HID device. It's usually the last HID device
|
||||
created. On Linux, for instance, this means the last reported hidraw
|
||||
in `dmesg` is the one you should do `cat /dev/hidrawX` on.
|
168
hw/application_fpga/tkey-libs/RELEASE.md
Normal file
168
hw/application_fpga/tkey-libs/RELEASE.md
Normal file
@ -0,0 +1,168 @@
|
||||
# Release notes
|
||||
|
||||
## Upcoming release
|
||||
|
||||
NOTE WELL! Rewritten I/O functions with new semantics!
|
||||
|
||||
### I/O
|
||||
|
||||
The Castor TKey hardware supports more USB endpoints:
|
||||
|
||||
- CDC - the same thing as older versions.
|
||||
- HID security token, for FIDO-like apps.
|
||||
- CTRL, a HID debug port.
|
||||
|
||||
The communication is still over a single UART. To differ between the
|
||||
endpoints we use an internal USB Mode Protocol between programs
|
||||
running on the PicoRV32 and the CH552 USB Controller.
|
||||
|
||||
The I/O functions has changed accordingly. Please use:
|
||||
|
||||
- `readselect()` with appropriate bitmask (e.g. `IO_CDC|IO_HID`) to
|
||||
see if there's anything to read in the endpoints you are interested
|
||||
in. Data from endpoints not mentioned in the bitmask will be
|
||||
discarded.
|
||||
|
||||
- `read()` is now non-blocking and returns the number of bytes read
|
||||
from the endpoint you specify, because more might not be available
|
||||
yet.
|
||||
|
||||
- `write()` now takes an endpoint destination.
|
||||
|
||||
- We also introduce generic `putchar()`, `puts()`, `puthex()`,
|
||||
`putinthex()`, and `hexdump()` functions that take a destination
|
||||
argument.
|
||||
|
||||
We recommend you use only these functions for I/O on Castor and going
|
||||
forward.
|
||||
|
||||
For compatibility to develop device apps for the Bellatrix platform
|
||||
and earlier, use the low-level, blocking function `uart_read()` for
|
||||
reads and *only* the `IO_UART` and `IO_QEMU` destinations for output
|
||||
functions like `write()`, `puts()`.
|
||||
|
||||
### Debug prints
|
||||
|
||||
The optionally built debug prints have changed. You now use
|
||||
`debug_puts()` et cetera instead of `qemu_*()`.
|
||||
|
||||
You define the debug output endpoint when you compile your program by
|
||||
including `debug.h` and defining `QEMU_DEBUG` for the qemu debug port
|
||||
or `TKEY_DEBUG` for output on the CTRL HID endpoint. If you don't
|
||||
define either, they won't appear in your code.
|
||||
|
||||
Similiarly, `assert()` now also follows `QEMU_DEBUG` or `TKEY_DEBUG`,
|
||||
and prints something on either before halting the CPU.
|
||||
|
||||
Note that on the Bellatrix platform only `QEMU_DEBUG` works.
|
||||
|
||||
## v0.1.2
|
||||
|
||||
From now on tkey-libs is licensed under the BSD-2-Clause license,
|
||||
moving from the previous GPLv2-only.
|
||||
|
||||
Note: There is a possibility that this update may impact the generated
|
||||
CDI for an app that relies on this library. It is recommended to
|
||||
always check for potential CDI changes for each specific app with
|
||||
every update. If the generated CDI does change, and if applicable, it
|
||||
should be clearly communicated to end users to prevent unintentional
|
||||
changes to their identity.
|
||||
|
||||
Changes:
|
||||
- New license, BSD-2-Clause
|
||||
- Reuse compliant, see https://reuse.software/
|
||||
- Fix row alignment in qemu_hexdump
|
||||
- Update memory map, tk1_mem.h, from canonical tillitis-key1 repo
|
||||
- Added make target for creating compile_commands.json for clangd
|
||||
- Added missing include in touch.h
|
||||
|
||||
Full changelog:
|
||||
[v0.1.1...v0.1.2](https://github.com/tillitis/tkey-libs/compare/v0.1.1...v0.1.2)
|
||||
|
||||
## v0.1.1
|
||||
|
||||
This is a minor release correcting a mistake and syncing with the
|
||||
latest HW release, TK1-24.03.
|
||||
|
||||
|
||||
Note: There is a possibility that this update may impact the generated
|
||||
CDI for an app that relies on this library. It is recommended to
|
||||
always check for potential CDI changes for each specific app with
|
||||
every update. If the generated CDI does change, and if applicable, it
|
||||
should be clearly communicated to end users to prevent unintentional
|
||||
changes to their identity.
|
||||
|
||||
Changes:
|
||||
- Update memory map, tk1_mem.h, to match the latest TK1-24.03 release.
|
||||
- Default to tkey-builder:4 for the podman target
|
||||
- Default to have QEMU debug enabled in tkey-libs. Mistakenly removed
|
||||
in previous release.
|
||||
- Revise readme accordingly
|
||||
|
||||
Full changelog:
|
||||
[v0.1.0...v0.1.1](https://github.com/tillitis/tkey-libs/compare/v0.1.0...v0.1.1)
|
||||
|
||||
## v0.1.0
|
||||
|
||||
This release contains some changes that forces applications that use
|
||||
tkey-libs to be updated to work with this release.
|
||||
|
||||
Note: It is highly likely that this update will affect the CDI of the
|
||||
TKey. It is advised to always verify this for each specific app, for
|
||||
every update. If the CDI changes, and it is applicable, it should be
|
||||
stated clearly to end users to avoid unknowingly changing the TKey
|
||||
identity.
|
||||
|
||||
Breaking changes:
|
||||
- Check destination buffer's size for read(). To prevent writing
|
||||
outside of destination buffer.
|
||||
- Renaming LED-functions to follow led_*().
|
||||
|
||||
Changes:
|
||||
- New function, secure_wipe(), to clean memory of secret data.
|
||||
- New function, touch_wait(). Waits for a touch by the user, with
|
||||
selectable timeout.
|
||||
- New function, led_get(). Get the value of the applied LED color.
|
||||
- Upgraded Monocypher to 4.0.2.
|
||||
- Add variable AR in Makefile to enabling passing llvm-ar from command
|
||||
line.
|
||||
- Update example app to use led.h.
|
||||
- Don't have QEMU debug enabled by default.
|
||||
- Minor tweaks and formatting.
|
||||
|
||||
Full changelog:
|
||||
[v0.0.2...v0.1.0](https://github.com/tillitis/tkey-libs/compare/v0.0.2...v0.1.0)
|
||||
|
||||
## v0.0.2
|
||||
|
||||
This release contains some changes that forces applications that use
|
||||
tkey-libs to be updated to work with this release.
|
||||
|
||||
Breaking changes:
|
||||
- Introducing include hierarchy to make it less generic, e.g.,
|
||||
`#include <tkey/led.h>`.
|
||||
- Use stdint.h/stddef.h infavor of types.h.
|
||||
- Library .a files built on top level to simplify inclusion.
|
||||
- Upgraded Monocypher to 4.0.1.
|
||||
- QEMU debug behaviour changed, instead of defining `NODEBUG` to
|
||||
disable debug, one has to enable it by defining `QEMU_DEBUG`.
|
||||
|
||||
Changes:
|
||||
- Introduce functions to control the LED, led.h and led.c.
|
||||
- New function, assert() to make an illegal instruction and forcing
|
||||
the CPU to halt.
|
||||
- Add functions memcpy_s(), wordcpy_s(), memeq() from firmware
|
||||
- Adding `const` to MMIO variables and qemu_* functions.
|
||||
- Minor tweaks, clean up and bugfixes.
|
||||
|
||||
Full changelog:
|
||||
[v0.0.1...v0.0.2](https://github.com/tillitis/tkey-libs/compare/v0.0.1...v0.0.2)
|
||||
|
||||
|
||||
## v0.0.1
|
||||
|
||||
Just ripped from
|
||||
|
||||
https://github.com/tillitis/tillitis-key1-apps
|
||||
|
||||
No semantic changes.
|
23
hw/application_fpga/tkey-libs/REUSE.toml
Normal file
23
hw/application_fpga/tkey-libs/REUSE.toml
Normal file
@ -0,0 +1,23 @@
|
||||
# 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",
|
||||
".gitignore",
|
||||
"example-app/Makefile",
|
||||
"monocypher/README.md",
|
||||
"Makefile",
|
||||
"README-DIST.txt",
|
||||
"README.md",
|
||||
"RELEASE.md"
|
||||
]
|
||||
SPDX-FileCopyrightText = "2022 Tillitis AB <tillitis.se>"
|
||||
SPDX-License-Identifier = "BSD-2-Clause"
|
64
hw/application_fpga/tkey-libs/app.lds
Normal file
64
hw/application_fpga/tkey-libs/app.lds
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 */
|
||||
}
|
33
hw/application_fpga/tkey-libs/example-app/Makefile
Normal file
33
hw/application_fpga/tkey-libs/example-app/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
P := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
LIBDIR ?= $(P)/../
|
||||
OBJCOPY ?= llvm-objcopy
|
||||
CC = clang
|
||||
|
||||
# If you want debug_puts() etcetera to output something on our QEMU
|
||||
# debug port, use -DQEMU_DEBUG below, or -DTKEY_DEBUG to use Tkeys USB debug pipe
|
||||
CFLAGS = -g -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 -nostdlib -mno-relax -flto \
|
||||
-Wall -Werror=implicit-function-declaration \
|
||||
-I $(LIBDIR)/include -I $(LIBDIR)
|
||||
# -DQEMU_DEBUG -DTKEY_DEBUG
|
||||
|
||||
INCLUDE=$(LIBDIR)/include
|
||||
|
||||
LDFLAGS=-T $(LIBDIR)/app.lds -L $(LIBDIR) -lcommon -lcrt0
|
||||
|
||||
.PHONY: all
|
||||
all: blue.bin
|
||||
|
||||
# Turn elf into bin for device
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $^ $@
|
||||
chmod a-x $@
|
||||
|
||||
BLUEOBJS=blue.o
|
||||
blue.elf: blue.o
|
||||
$(CC) $(CFLAGS) $(BLUEOBJS) $(LDFLAGS) -I $(LIBDIR) -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f blue.bin blue.elf $(BLUEOBJS)
|
31
hw/application_fpga/tkey-libs/example-app/blue.c
Normal file
31
hw/application_fpga/tkey-libs/example-app/blue.c
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tkey/led.h>
|
||||
#include <tkey/tk1_mem.h>
|
||||
#include <tkey/debug.h>
|
||||
|
||||
#define SLEEPTIME 100000
|
||||
|
||||
void sleep(uint32_t n)
|
||||
{
|
||||
for (volatile int i = 0; i < n; i++);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
debug_puts("Hello, world!\n");
|
||||
debug_puts("Going to sleep between blinks: ");
|
||||
debug_putinthex(SLEEPTIME);
|
||||
debug_lf();
|
||||
|
||||
for (;;) {
|
||||
led_set(LED_RED);
|
||||
sleep(SLEEPTIME);
|
||||
led_set(LED_GREEN);
|
||||
sleep(SLEEPTIME);
|
||||
led_set(LED_BLUE);
|
||||
sleep(SLEEPTIME);
|
||||
}
|
||||
}
|
29
hw/application_fpga/tkey-libs/include/tkey/assert.h
Normal file
29
hw/application_fpga/tkey-libs/include/tkey/assert.h
Normal file
@ -0,0 +1,29 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#ifndef TKEY_ASSERT_H
|
||||
#define TKEY_ASSERT_H
|
||||
|
||||
#include <tkey/io.h>
|
||||
|
||||
#if defined(QEMU_DEBUG)
|
||||
#define assert(expr) \
|
||||
((expr) ? (void)(0) \
|
||||
: assert_fail(IO_QEMU, #expr, __FILE__, __LINE__, __func__))
|
||||
|
||||
#elif defined(TKEY_DEBUG)
|
||||
|
||||
#define assert(expr) \
|
||||
((expr) \
|
||||
? (void)(0) \
|
||||
: assert_fail(IO_TKEYCTRL, #expr, __FILE__, __LINE__, __func__))
|
||||
|
||||
#else
|
||||
|
||||
#define assert(expr) ((expr) ? (void)(0) : assert_halt())
|
||||
#endif
|
||||
|
||||
void assert_fail(enum ioend dest, const char *assertion, const char *file,
|
||||
unsigned int line, const char *function);
|
||||
void assert_halt(void);
|
||||
#endif
|
22
hw/application_fpga/tkey-libs/include/tkey/blake2s.h
Normal file
22
hw/application_fpga/tkey-libs/include/tkey/blake2s.h
Normal file
@ -0,0 +1,22 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#ifndef TKEY_BLAKE2S_H
|
||||
#define TKEY_BLAKE2S_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// blake2s state context
|
||||
typedef struct {
|
||||
uint8_t b[64]; // input buffer
|
||||
uint32_t h[8]; // chained state
|
||||
uint32_t t[2]; // total number of bytes
|
||||
size_t c; // pointer for b[]
|
||||
size_t outlen; // digest size
|
||||
} blake2s_ctx;
|
||||
|
||||
int blake2s(void *out, unsigned long outlen, const void *key,
|
||||
unsigned long keylen, const void *in, unsigned long inlen,
|
||||
blake2s_ctx *ctx);
|
||||
#endif
|
39
hw/application_fpga/tkey-libs/include/tkey/debug.h
Normal file
39
hw/application_fpga/tkey-libs/include/tkey/debug.h
Normal file
@ -0,0 +1,39 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#ifndef TKEY_DEBUG_H
|
||||
#define TKEY_DEBUG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "io.h"
|
||||
|
||||
#if defined(QEMU_DEBUG)
|
||||
#define debug_putchar(ch) putchar(IO_QEMU, ch)
|
||||
#define debug_lf() putchar(IO_QEMU, '\n')
|
||||
#define debug_putinthex(ch) putinthex(IO_QEMU, ch)
|
||||
#define debug_puts(s) puts(IO_QEMU, s)
|
||||
#define debug_puthex(ch) puthex(IO_QEMU, ch)
|
||||
#define debug_hexdump(buf, len) hexdump(IO_QEMU, buf, len)
|
||||
|
||||
#elif defined(TKEY_DEBUG)
|
||||
|
||||
#define debug_putchar(ch) putchar(IO_TKEYCTRL, ch)
|
||||
#define debug_lf() putchar(IO_TKEYCTRL, '\n')
|
||||
#define debug_putinthex(ch) putinthex(IO_TKEYCTRL, ch)
|
||||
#define debug_puts(s) puts(IO_TKEYCTRL, s)
|
||||
#define debug_puthex(ch) puthex(IO_TKEYCTRL, ch)
|
||||
#define debug_hexdump(buf, len) hexdump(IO_TKEYCTRL, buf, len)
|
||||
|
||||
#else
|
||||
|
||||
#define debug_putchar(ch)
|
||||
#define debug_lf()
|
||||
#define debug_putinthex(n)
|
||||
#define debug_puts(s)
|
||||
#define debug_puthex(ch)
|
||||
#define debug_hexdump(buf, len)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
33
hw/application_fpga/tkey-libs/include/tkey/io.h
Normal file
33
hw/application_fpga/tkey-libs/include/tkey/io.h
Normal file
@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef TKEY_IO_H
|
||||
#define TKEY_IO_H
|
||||
|
||||
// I/O endpoints. Keep it as bits possible to use in a bitmask in
|
||||
// readselect().
|
||||
//
|
||||
// Note that the the TKEYCTRL, CDC, and HID should be kept the same on
|
||||
// the CH552 side.
|
||||
enum ioend {
|
||||
IO_NONE = 0x00, // No endpoint
|
||||
IO_UART = 0x01, // Only destination, raw UART access
|
||||
IO_QEMU = 0x10, // Only destination, QEMU debug port
|
||||
IO_TKEYCTRL = 0x20, // HID debug port
|
||||
IO_CDC = 0x40, // CDC "serial port"
|
||||
IO_HID = 0x80, // HID security token
|
||||
};
|
||||
|
||||
void write(enum ioend dest, const uint8_t *buf, size_t nbytes);
|
||||
int read(enum ioend src, uint8_t *buf, size_t bufsize, size_t nbytes);
|
||||
int uart_read(uint8_t *buf, size_t bufsize, size_t nbytes);
|
||||
int readselect(int bitmask, enum ioend *endpoint, uint8_t *len);
|
||||
void putchar(enum ioend dest, const uint8_t ch);
|
||||
void puthex(enum ioend dest, const uint8_t ch);
|
||||
void putinthex(enum ioend dest, const uint32_t n);
|
||||
void puts(enum ioend dest, const char *s);
|
||||
void hexdump(enum ioend dest, void *buf, int len);
|
||||
#endif
|
21
hw/application_fpga/tkey-libs/include/tkey/led.h
Normal file
21
hw/application_fpga/tkey-libs/include/tkey/led.h
Normal file
@ -0,0 +1,21 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#ifndef TKEY_LED_H
|
||||
#define TKEY_LED_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tkey/tk1_mem.h>
|
||||
|
||||
// clang-format off
|
||||
#define LED_BLACK 0
|
||||
#define LED_RED (1 << TK1_MMIO_TK1_LED_R_BIT)
|
||||
#define LED_GREEN (1 << TK1_MMIO_TK1_LED_G_BIT)
|
||||
#define LED_BLUE (1 << TK1_MMIO_TK1_LED_B_BIT)
|
||||
#define LED_WHITE (LED_RED | LED_GREEN | LED_BLUE)
|
||||
// clang-format on
|
||||
|
||||
uint32_t led_get(void);
|
||||
void led_set(uint32_t ledvalue);
|
||||
void led_flash_forever(uint32_t ledvalue);
|
||||
#endif
|
18
hw/application_fpga/tkey-libs/include/tkey/lib.h
Normal file
18
hw/application_fpga/tkey-libs/include/tkey/lib.h
Normal file
@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#ifndef TKEY_LIB_H
|
||||
#define TKEY_LIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void *memset(void *dest, int c, unsigned n);
|
||||
void *memcpy(void *dest, const void *src, unsigned n);
|
||||
void memcpy_s(void *dest, size_t destsize, const void *src, size_t n);
|
||||
void *wordcpy(void *dest, const void *src, unsigned n);
|
||||
void wordcpy_s(void *dest, size_t destsize, const void *src, size_t n);
|
||||
int memeq(void *dest, const void *src, size_t n);
|
||||
void secure_wipe(void *v, size_t n);
|
||||
size_t strlen(const char *str);
|
||||
#endif
|
39
hw/application_fpga/tkey-libs/include/tkey/proto.h
Normal file
39
hw/application_fpga/tkey-libs/include/tkey/proto.h
Normal file
@ -0,0 +1,39 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef TKEY_PROTO_H
|
||||
#define TKEY_PROTO_H
|
||||
|
||||
enum endpoints {
|
||||
DST_HW_IFPGA = 0x00,
|
||||
DST_HW_AFPGA = 0x01,
|
||||
DST_FW = 0x02,
|
||||
DST_SW = 0x03
|
||||
};
|
||||
|
||||
enum cmdlen {
|
||||
LEN_1,
|
||||
LEN_4,
|
||||
LEN_32,
|
||||
LEN_128
|
||||
};
|
||||
|
||||
#define CMDLEN_MAXBYTES 128
|
||||
|
||||
enum status {
|
||||
STATUS_OK,
|
||||
STATUS_BAD
|
||||
};
|
||||
|
||||
struct frame_header {
|
||||
uint8_t id;
|
||||
enum endpoints endpoint;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status, enum cmdlen len);
|
||||
int parseframe(uint8_t b, struct frame_header *hdr);
|
||||
#endif
|
148
hw/application_fpga/tkey-libs/include/tkey/tk1_mem.h
Normal file
148
hw/application_fpga/tkey-libs/include/tkey/tk1_mem.h
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Tillitis TKey Memory Map
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Note that this file is also in tillitis-key1 and qemu
|
||||
* (GPL-2.0-or-later). Needs to stay in sync and have a compatible
|
||||
* license.
|
||||
*/
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef TKEY_TK1_MEM_H
|
||||
#define TKEY_TK1_MEM_H
|
||||
|
||||
/*
|
||||
The canonical location of this file is in:
|
||||
|
||||
https://github.com/tillitis/tkey-libs
|
||||
|
||||
Under:
|
||||
|
||||
include/tkey/tk1_mem.h
|
||||
|
||||
The contents are mostly derived from the Verilog code in
|
||||
|
||||
https://github.com/tillitis/tillitis-key1
|
||||
|
||||
Memory map
|
||||
|
||||
Top level prefix, the first 2 bits in a 32-bit address:
|
||||
|
||||
name prefix address length
|
||||
--------------------------------------------------------
|
||||
ROM 0b00 30 bit address
|
||||
RAM 0b01 30 bit address
|
||||
Reserved 0b10
|
||||
Cores 0b11 6 bits for core select, 24 bits rest
|
||||
|
||||
Address Prefix, the first 8 bits in a 32-bit address:
|
||||
|
||||
name prefix
|
||||
--------------------
|
||||
ROM 0x00
|
||||
RAM 0x40
|
||||
TRNG 0xc0
|
||||
TIMER 0xc1
|
||||
UDS 0xc2
|
||||
UART 0xc3
|
||||
TOUCH 0xc4
|
||||
FW_RAM 0xd0
|
||||
QEMU 0xfe Not used in real hardware
|
||||
TK1 0xff
|
||||
*/
|
||||
|
||||
#define TK1_ROM_BASE 0x00000000
|
||||
#define TK1_ROM_SIZE 0x2000
|
||||
|
||||
#define TK1_RAM_BASE 0x40000000
|
||||
#define TK1_RAM_SIZE 0x20000
|
||||
|
||||
#define TK1_MMIO_BASE 0xc0000000
|
||||
#define TK1_MMIO_SIZE 0x3fffffff
|
||||
|
||||
#define TK1_APP_MAX_SIZE 0x20000
|
||||
|
||||
#define TK1_MMIO_FW_RAM_BASE 0xd0000000
|
||||
// FW_RAM is 4096 bytes
|
||||
#define TK1_MMIO_FW_RAM_SIZE 0x1000
|
||||
|
||||
#define TK1_MMIO_TRNG_BASE 0xc0000000
|
||||
#define TK1_MMIO_TRNG_STATUS 0xc0000024
|
||||
#define TK1_MMIO_TRNG_STATUS_READY_BIT 0
|
||||
#define TK1_MMIO_TRNG_ENTROPY 0xc0000080
|
||||
|
||||
#define TK1_MMIO_TIMER_BASE 0xc1000000
|
||||
#define TK1_MMIO_TIMER_CTRL 0xc1000020
|
||||
#define TK1_MMIO_TIMER_CTRL_START_BIT 0
|
||||
#define TK1_MMIO_TIMER_CTRL_STOP_BIT 1
|
||||
|
||||
#define TK1_MMIO_TIMER_STATUS 0xc1000024
|
||||
#define TK1_MMIO_TIMER_STATUS_RUNNING_BIT 0
|
||||
#define TK1_MMIO_TIMER_PRESCALER 0xc1000028
|
||||
#define TK1_MMIO_TIMER_TIMER 0xc100002c
|
||||
|
||||
#define TK1_MMIO_UDS_BASE 0xc2000000
|
||||
#define TK1_MMIO_UDS_FIRST 0xc2000000
|
||||
#define TK1_MMIO_UDS_LAST 0xc200001c
|
||||
|
||||
#define TK1_MMIO_UART_BASE 0xc3000000
|
||||
#define TK1_MMIO_UART_RX_STATUS 0xc3000080
|
||||
#define TK1_MMIO_UART_RX_DATA 0xc3000084
|
||||
#define TK1_MMIO_UART_RX_BYTES 0xc3000088
|
||||
#define TK1_MMIO_UART_TX_STATUS 0xc3000100
|
||||
#define TK1_MMIO_UART_TX_DATA 0xc3000104
|
||||
|
||||
#define TK1_MMIO_TOUCH_BASE 0xc4000000
|
||||
#define TK1_MMIO_TOUCH_STATUS 0xc4000024
|
||||
#define TK1_MMIO_TOUCH_STATUS_EVENT_BIT 0
|
||||
|
||||
// This only exists in QEMU, not real hardware
|
||||
#define TK1_MMIO_QEMU_BASE 0xfe000000
|
||||
#define TK1_MMIO_QEMU_DEBUG 0xfe001000
|
||||
|
||||
#define TK1_MMIO_TK1_BASE 0xff000000
|
||||
|
||||
#define TK1_MMIO_TK1_NAME0 0xff000000
|
||||
#define TK1_MMIO_TK1_NAME1 0xff000004
|
||||
#define TK1_MMIO_TK1_VERSION 0xff000008
|
||||
|
||||
#define TK1_MMIO_TK1_LED 0xff000024
|
||||
#define TK1_MMIO_TK1_LED_R_BIT 2
|
||||
#define TK1_MMIO_TK1_LED_G_BIT 1
|
||||
#define TK1_MMIO_TK1_LED_B_BIT 0
|
||||
|
||||
#define TK1_MMIO_TK1_GPIO 0xff000028
|
||||
#define TK1_MMIO_TK1_GPIO1_BIT 0
|
||||
#define TK1_MMIO_TK1_GPIO2_BIT 1
|
||||
#define TK1_MMIO_TK1_GPIO3_BIT 2
|
||||
#define TK1_MMIO_TK1_GPIO4_BIT 3
|
||||
|
||||
#define TK1_MMIO_TK1_APP_ADDR 0xff000030
|
||||
#define TK1_MMIO_TK1_APP_SIZE 0xff000034
|
||||
|
||||
#define TK1_MMIO_TK1_CDI_FIRST 0xff000080
|
||||
#define TK1_MMIO_TK1_CDI_LAST 0xff00009c
|
||||
|
||||
#define TK1_MMIO_TK1_UDI_FIRST 0xff0000c0
|
||||
#define TK1_MMIO_TK1_UDI_LAST 0xff0000c4
|
||||
|
||||
// Deprecated - use _ADDR_RAND instead
|
||||
#define TK1_MMIO_TK1_RAM_ASLR 0xff000100
|
||||
#define TK1_MMIO_TK1_RAM_ADDR_RAND 0xff000100
|
||||
// Deprecated - use _DATA_RAND instead
|
||||
#define TK1_MMIO_TK1_RAM_SCRAMBLE 0xff000104
|
||||
#define TK1_MMIO_TK1_RAM_DATA_RAND 0xff000104
|
||||
|
||||
#define TK1_MMIO_TK1_CPU_MON_CTRL 0xff000180
|
||||
#define TK1_MMIO_TK1_CPU_MON_FIRST 0xff000184
|
||||
#define TK1_MMIO_TK1_CPU_MON_LAST 0xff000188
|
||||
|
||||
#define TK1_MMIO_TK1_SYSTEM_RESET 0xff0001C0
|
||||
|
||||
#define TK1_MMIO_TK1_SPI_EN 0xff000200
|
||||
#define TK1_MMIO_TK1_SPI_XFER 0xff000204
|
||||
#define TK1_MMIO_TK1_SPI_DATA 0xff000208
|
||||
#endif
|
17
hw/application_fpga/tkey-libs/include/tkey/touch.h
Normal file
17
hw/application_fpga/tkey-libs/include/tkey/touch.h
Normal file
@ -0,0 +1,17 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#ifndef TKEY_TOUCH_H
|
||||
#define TKEY_TOUCH_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <tkey/tk1_mem.h>
|
||||
|
||||
// touchwait() waits for a touch event while blinking color on the
|
||||
// status LED. timeout_s is the timeout in seconds.
|
||||
//
|
||||
// If a touch event occurs it returns true. If the timeout expires it
|
||||
// returns false.
|
||||
bool touch_wait(int color, int timeout_s);
|
||||
#endif
|
35
hw/application_fpga/tkey-libs/libcommon/assert.c
Normal file
35
hw/application_fpga/tkey-libs/libcommon/assert.c
Normal file
@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <tkey/assert.h>
|
||||
#include <tkey/io.h>
|
||||
#include <tkey/lib.h>
|
||||
|
||||
void assert_fail(enum ioend dest, const char *assertion, const char *file,
|
||||
unsigned int line, const char *function)
|
||||
{
|
||||
puts(dest, "assert: ");
|
||||
puts(dest, assertion);
|
||||
puts(dest, " ");
|
||||
puts(dest, file);
|
||||
puts(dest, ":");
|
||||
putinthex(dest, line);
|
||||
puts(dest, " ");
|
||||
puts(dest, function);
|
||||
puts(dest, "\n");
|
||||
|
||||
// Force illegal instruction to halt CPU
|
||||
asm volatile("unimp");
|
||||
|
||||
// Not reached
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void assert_halt(void)
|
||||
{
|
||||
// Force illegal instruction to halt CPU
|
||||
asm volatile("unimp");
|
||||
|
||||
// Not reached
|
||||
__builtin_unreachable();
|
||||
}
|
14
hw/application_fpga/tkey-libs/libcommon/blake2s.c
Normal file
14
hw/application_fpga/tkey-libs/libcommon/blake2s.c
Normal file
@ -0,0 +1,14 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tkey/blake2s.h>
|
||||
#include <tkey/tk1_mem.h>
|
||||
|
||||
int blake2s(void *out, unsigned long outlen, const void *key,
|
||||
unsigned long keylen, const void *in, unsigned long inlen,
|
||||
blake2s_ctx *ctx)
|
||||
{
|
||||
// Not implemented.
|
||||
return -1;
|
||||
}
|
350
hw/application_fpga/tkey-libs/libcommon/io.c
Normal file
350
hw/application_fpga/tkey-libs/libcommon/io.c
Normal file
@ -0,0 +1,350 @@
|
||||
// SPDX-FileCopyrightText: 2025 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tkey/assert.h>
|
||||
#include <tkey/debug.h>
|
||||
#include <tkey/lib.h>
|
||||
#include <tkey/proto.h>
|
||||
#include <tkey/tk1_mem.h>
|
||||
|
||||
// Maximum payload size sent over the USB Mode Protocol.
|
||||
//
|
||||
// USB Mode Protocol:
|
||||
// 1 byte mode
|
||||
// 1 byte length
|
||||
//
|
||||
// Our USB Mode Protocol packets has room for 255 bytes according to
|
||||
// the header but we send at most 64 bytes of payload + the 2 byte
|
||||
// header. The header is removed in the USB controller and the maximum
|
||||
// payload fits in a single USB frame on the other side.
|
||||
#define USBMODE_PACKET_SIZE 64
|
||||
|
||||
static void hex(uint8_t buf[2], const uint8_t c);
|
||||
static int discard(size_t nbytes);
|
||||
static uint8_t readbyte(void);
|
||||
static void writebyte(uint8_t b);
|
||||
|
||||
struct usb_mode {
|
||||
enum ioend endpoint; // Current USB endpoint with data
|
||||
uint8_t len; // Data available in from current USB mode.
|
||||
};
|
||||
|
||||
static struct usb_mode cur_endpoint = {
|
||||
IO_NONE,
|
||||
0,
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
static volatile uint32_t* const can_rx = (volatile uint32_t *)TK1_MMIO_UART_RX_STATUS;
|
||||
static volatile uint32_t* const rx = (volatile uint32_t *)TK1_MMIO_UART_RX_DATA;
|
||||
static volatile uint32_t* const can_tx = (volatile uint32_t *)TK1_MMIO_UART_TX_STATUS;
|
||||
static volatile uint32_t* const tx = (volatile uint32_t *)TK1_MMIO_UART_TX_DATA;
|
||||
static volatile uint8_t* const debugtx = (volatile uint8_t *)TK1_MMIO_QEMU_DEBUG;
|
||||
// clang-format on
|
||||
|
||||
// writebyte blockingly writes byte b to UART
|
||||
static void writebyte(uint8_t b)
|
||||
{
|
||||
for (;;) {
|
||||
if (*can_tx) {
|
||||
*tx = b;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write_with_header writes nbytes of buf to UART with a USB Mode
|
||||
// Protocol header telling the receiver about the mode and length.
|
||||
static void write_with_header(enum ioend dest, const uint8_t *buf,
|
||||
size_t nbytes)
|
||||
{
|
||||
// USB Mode Protocol header:
|
||||
// 1 byte mode
|
||||
// 1 byte length
|
||||
|
||||
writebyte(dest);
|
||||
writebyte(nbytes);
|
||||
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
writebyte(buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// write blockingly writes nbytes bytes of data from buf to dest which
|
||||
// is either:
|
||||
//
|
||||
// - IO_QEMU: QEMU debug port
|
||||
//
|
||||
// - IO_UART: Low-level UART access, no USB Mode Header added.
|
||||
//
|
||||
// - IO_CDC: Through the UART for the CDC endpoint, with header.
|
||||
//
|
||||
// - IO_HID: Through the UART for the HID endpoint, with header.
|
||||
//
|
||||
// - IO_TKEYCTRL: Through the UART for the debug HID endpoint, with
|
||||
// header.
|
||||
void write(enum ioend dest, const uint8_t *buf, size_t nbytes)
|
||||
{
|
||||
if (dest == IO_QEMU) {
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
*debugtx = buf[i];
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (dest == IO_UART) {
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
writebyte(buf[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while (nbytes > 0) {
|
||||
// We split the data into chunks that will fit in the
|
||||
// USB Mode Protocol and fits neatly in the USB frames
|
||||
// on the other side of the USB controller.
|
||||
uint8_t len =
|
||||
nbytes < USBMODE_PACKET_SIZE ? nbytes : USBMODE_PACKET_SIZE;
|
||||
|
||||
write_with_header(dest, (const uint8_t *)buf, len);
|
||||
|
||||
buf += len;
|
||||
nbytes -= len;
|
||||
}
|
||||
}
|
||||
|
||||
// readbyte reads a byte from UART and returns it. Blocking.
|
||||
static uint8_t readbyte(void)
|
||||
{
|
||||
for (;;) {
|
||||
if (*can_rx) {
|
||||
return *rx;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read reads into buf of size bufsize from UART, nbytes or less, from
|
||||
// the current USB endpoint. It doesn't block.
|
||||
//
|
||||
// Returns the number of bytes read. Empty data returns 0.
|
||||
int read(enum ioend src, uint8_t *buf, size_t bufsize, size_t nbytes)
|
||||
{
|
||||
if (buf == NULL || nbytes > bufsize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (src == IO_NONE || src == IO_UART || src == IO_QEMU) {
|
||||
// Destination only endpoints
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (src != cur_endpoint.endpoint) {
|
||||
// No data for this source available right now.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
|
||||
for (n = 0; n < nbytes; n++) {
|
||||
buf[n] = readbyte();
|
||||
cur_endpoint.len--;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
// uart_read reads blockingly into buf o size bufsize from UART nbytes
|
||||
// bytes.
|
||||
//
|
||||
// Returns negative on error.
|
||||
int uart_read(uint8_t *buf, size_t bufsize, size_t nbytes)
|
||||
{
|
||||
if (nbytes > bufsize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int n = 0; n < nbytes; n++) {
|
||||
buf[n] = readbyte();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// discard nbytes of what's available.
|
||||
//
|
||||
// Returns how many bytes were discarded.
|
||||
static int discard(size_t nbytes)
|
||||
{
|
||||
int n = 0;
|
||||
uint8_t len = nbytes < cur_endpoint.len ? nbytes : cur_endpoint.len;
|
||||
|
||||
for (n = 0; n < len; n++) {
|
||||
(void)readbyte();
|
||||
cur_endpoint.len--;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
// readselect blocks and returns when there is something readable from
|
||||
// some mode.
|
||||
//
|
||||
// Use like this:
|
||||
//
|
||||
// readselect(IO_CDC|IO_HID, &endpoint, &len)
|
||||
//
|
||||
// to wait for some data from either the CDC or the HID endpoint.
|
||||
//
|
||||
// NOTE WELL: You need to call readselect() first, before doing any
|
||||
// calls to read().
|
||||
//
|
||||
// Only endpoints available for read are:
|
||||
//
|
||||
// - IO_TKEYCTRL
|
||||
// - IO_CDC
|
||||
// - IO_HID
|
||||
//
|
||||
// If you need blocking low-level UART reads, use uart_read() instead.
|
||||
//
|
||||
// Sets endpoint of the first endpoint in the bitmask with data
|
||||
// available. Indicates how many bytes available in len.
|
||||
//
|
||||
// Returns non-zero on error.
|
||||
int readselect(int bitmask, enum ioend *endpoint, uint8_t *len)
|
||||
{
|
||||
if (bitmask & IO_UART || bitmask & IO_QEMU) {
|
||||
// Not possible to use readselect() on these
|
||||
// endpoints.
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
// Check what is in the current UART buffer.
|
||||
//
|
||||
// - If nothing known, block until something comes along.
|
||||
//
|
||||
// - If not in bitmask, discard the data available
|
||||
// from that endpoint.
|
||||
//
|
||||
// - If in the bitmask, return the first endpoint with
|
||||
// data available and indicate how much data in len.
|
||||
if (cur_endpoint.len == 0) {
|
||||
// Read USB Mode Protocol header:
|
||||
// 1 byte mode
|
||||
// 1 byte length
|
||||
cur_endpoint.endpoint = readbyte();
|
||||
cur_endpoint.len = readbyte();
|
||||
}
|
||||
|
||||
*len = cur_endpoint.len;
|
||||
|
||||
if (cur_endpoint.endpoint & bitmask) {
|
||||
*endpoint = cur_endpoint.endpoint;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Not the USB endpoint caller asked for. Discard the
|
||||
// rest from this endpoint.
|
||||
if (discard(*len) != *len) {
|
||||
// We couldn't discard what the USB Mode
|
||||
// Protocol itself reported was available!
|
||||
// Something's fishy. Halt.
|
||||
assert(1 == 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void putchar(enum ioend dest, const uint8_t ch)
|
||||
{
|
||||
write(dest, &ch, 1);
|
||||
}
|
||||
|
||||
static void hex(uint8_t buf[2], const uint8_t c)
|
||||
{
|
||||
unsigned int upper = (c >> 4) & 0xf;
|
||||
unsigned int lower = c & 0xf;
|
||||
|
||||
buf[0] = upper < 10 ? '0' + upper : 'a' - 10 + upper;
|
||||
buf[1] = lower < 10 ? '0' + lower : 'a' - 10 + lower;
|
||||
}
|
||||
|
||||
void puthex(enum ioend dest, const uint8_t c)
|
||||
{
|
||||
uint8_t hexbuf[2] = {0};
|
||||
|
||||
hex(hexbuf, c);
|
||||
write(dest, hexbuf, 2);
|
||||
}
|
||||
|
||||
// Size of of a maximum integer in hex text format
|
||||
#define INTBUFSIZE 10
|
||||
|
||||
void putinthex(enum ioend dest, const uint32_t n)
|
||||
{
|
||||
uint8_t buf[INTBUFSIZE] = {0};
|
||||
uint8_t hexbuf[2] = {0};
|
||||
uint8_t *intbuf = (uint8_t *)&n;
|
||||
int j = 0;
|
||||
|
||||
buf[j++] = '0';
|
||||
buf[j++] = 'x';
|
||||
|
||||
for (int i = 3; i > -1; i--) {
|
||||
hex(hexbuf, intbuf[i]);
|
||||
buf[j++] = hexbuf[0];
|
||||
buf[j++] = hexbuf[1];
|
||||
}
|
||||
|
||||
write(dest, buf, INTBUFSIZE);
|
||||
}
|
||||
|
||||
void puts(enum ioend dest, const char *s)
|
||||
{
|
||||
write(dest, (const uint8_t *)s, strlen(s));
|
||||
}
|
||||
|
||||
// Size of a hex row: Contains 16 bytes where each byte is printed as
|
||||
// 3 characters (hex + hex + space). Every row ends with newline or at
|
||||
// most CR+LF.
|
||||
#define FULLROW (16 * 3)
|
||||
#define ROWBUFSIZE (FULLROW + 2)
|
||||
|
||||
void hexdump(enum ioend dest, void *buf, int len)
|
||||
{
|
||||
uint8_t rowbuf[ROWBUFSIZE] = {0};
|
||||
uint8_t hexbuf[2] = {0};
|
||||
uint8_t *byte_buf = (uint8_t *)buf;
|
||||
|
||||
int rowpos = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
hex(hexbuf, byte_buf[i]);
|
||||
rowbuf[rowpos++] = hexbuf[0];
|
||||
rowbuf[rowpos++] = hexbuf[1];
|
||||
rowbuf[rowpos++] = ' ';
|
||||
|
||||
// If the row is full, print it now.
|
||||
if (rowpos == FULLROW) {
|
||||
if (dest == IO_CDC) {
|
||||
rowbuf[rowpos++] = '\r';
|
||||
}
|
||||
rowbuf[rowpos++] = '\n';
|
||||
write(dest, rowbuf, rowpos);
|
||||
rowpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If final row wasn't full, print it now.
|
||||
if (rowpos != 0) {
|
||||
if (dest == IO_CDC) {
|
||||
rowbuf[rowpos++] = '\r';
|
||||
}
|
||||
rowbuf[rowpos++] = '\n';
|
||||
write(dest, rowbuf, rowpos);
|
||||
}
|
||||
}
|
31
hw/application_fpga/tkey-libs/libcommon/led.c
Normal file
31
hw/application_fpga/tkey-libs/libcommon/led.c
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tkey/led.h>
|
||||
|
||||
// clang-format off
|
||||
static volatile uint32_t* const led = (volatile uint32_t *)TK1_MMIO_TK1_LED;
|
||||
// clang-format on
|
||||
|
||||
void led_set(uint32_t ledvalue)
|
||||
{
|
||||
*led = ledvalue;
|
||||
}
|
||||
|
||||
uint32_t led_get()
|
||||
{
|
||||
return *led;
|
||||
}
|
||||
|
||||
void led_flash_forever(uint32_t ledvalue)
|
||||
{
|
||||
int led_on = 0;
|
||||
|
||||
for (;;) {
|
||||
*led = led_on ? ledvalue : LED_BLACK;
|
||||
for (volatile int i = 0; i < 800000; i++) {
|
||||
}
|
||||
led_on = !led_on;
|
||||
}
|
||||
}
|
101
hw/application_fpga/tkey-libs/libcommon/lib.c
Normal file
101
hw/application_fpga/tkey-libs/libcommon/lib.c
Normal file
@ -0,0 +1,101 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tkey/assert.h>
|
||||
#include <tkey/lib.h>
|
||||
#include <tkey/tk1_mem.h>
|
||||
|
||||
void *memset(void *dest, int c, unsigned n)
|
||||
{
|
||||
uint8_t *s = dest;
|
||||
|
||||
for (; n; n--, s++)
|
||||
*s = c;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
__attribute__((used)) void *memcpy(void *dest, const void *src, unsigned n)
|
||||
{
|
||||
uint8_t *src_byte = (uint8_t *)src;
|
||||
uint8_t *dest_byte = (uint8_t *)dest;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
dest_byte[i] = src_byte[i];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void memcpy_s(void *dest, size_t destsize, const void *src, size_t n)
|
||||
{
|
||||
assert(dest != NULL);
|
||||
assert(src != NULL);
|
||||
assert(destsize >= n);
|
||||
|
||||
uint8_t *src_byte = (uint8_t *)src;
|
||||
uint8_t *dest_byte = (uint8_t *)dest;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
dest_byte[i] = src_byte[i];
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((used)) void *wordcpy(void *dest, const void *src, unsigned n)
|
||||
{
|
||||
uint32_t *src_word = (uint32_t *)src;
|
||||
uint32_t *dest_word = (uint32_t *)dest;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
dest_word[i] = src_word[i];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void wordcpy_s(void *dest, size_t destsize, const void *src, size_t n)
|
||||
{
|
||||
assert(dest != NULL);
|
||||
assert(src != NULL);
|
||||
assert(destsize >= n);
|
||||
|
||||
uint32_t *src_word = (uint32_t *)src;
|
||||
uint32_t *dest_word = (uint32_t *)dest;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
dest_word[i] = src_word[i];
|
||||
}
|
||||
}
|
||||
|
||||
int memeq(void *dest, const void *src, size_t n)
|
||||
{
|
||||
uint8_t *src_byte = (uint8_t *)src;
|
||||
uint8_t *dest_byte = (uint8_t *)dest;
|
||||
int res = -1;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (dest_byte[i] != src_byte[i]) {
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void secure_wipe(void *v, size_t n)
|
||||
{
|
||||
volatile uint8_t *p = (volatile uint8_t *)v;
|
||||
while (n--)
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
size_t strlen(const char *str)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s; ++s)
|
||||
;
|
||||
|
||||
return (s - str);
|
||||
}
|
51
hw/application_fpga/tkey-libs/libcommon/proto.c
Normal file
51
hw/application_fpga/tkey-libs/libcommon/proto.c
Normal file
@ -0,0 +1,51 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <tkey/assert.h>
|
||||
#include <tkey/debug.h>
|
||||
#include <tkey/proto.h>
|
||||
#include <tkey/tk1_mem.h>
|
||||
|
||||
uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status, enum cmdlen len)
|
||||
{
|
||||
return (id << 5) | (endpoint << 3) | (status << 2) | len;
|
||||
}
|
||||
|
||||
int parseframe(uint8_t b, struct frame_header *hdr)
|
||||
{
|
||||
if ((b & 0x80) != 0) {
|
||||
// Bad version
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((b & 0x4) != 0) {
|
||||
// Must be 0
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr->id = (b & 0x60) >> 5;
|
||||
hdr->endpoint = (b & 0x18) >> 3;
|
||||
|
||||
// Length
|
||||
switch (b & 0x3) {
|
||||
case LEN_1:
|
||||
hdr->len = 1;
|
||||
break;
|
||||
case LEN_4:
|
||||
hdr->len = 4;
|
||||
break;
|
||||
case LEN_32:
|
||||
hdr->len = 32;
|
||||
break;
|
||||
case LEN_128:
|
||||
hdr->len = 128;
|
||||
break;
|
||||
default:
|
||||
// Unknown length
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
67
hw/application_fpga/tkey-libs/libcommon/touch.c
Normal file
67
hw/application_fpga/tkey-libs/libcommon/touch.c
Normal file
@ -0,0 +1,67 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tillitis AB <tillitis.se>
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <tkey/debug.h>
|
||||
#include <tkey/led.h>
|
||||
#include <tkey/touch.h>
|
||||
|
||||
// CPU clock frequenzy in Hz
|
||||
#define CPUFREQ 18000000
|
||||
|
||||
// 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;
|
||||
static volatile uint32_t *touch = (volatile uint32_t *)TK1_MMIO_TOUCH_STATUS;
|
||||
// clang-format on
|
||||
|
||||
// Returns !0 if touch sensor has been touched
|
||||
#define touched() (*touch & (1 << TK1_MMIO_TOUCH_STATUS_EVENT_BIT))
|
||||
|
||||
bool touch_wait(int color, int timeout_s)
|
||||
{
|
||||
int ledon = 0;
|
||||
int orig_color = led_get();
|
||||
uint32_t time = 0;
|
||||
uint32_t lasttime = 0;
|
||||
|
||||
// Tick once every decisecond
|
||||
*timer_prescaler = CPUFREQ / 10;
|
||||
*timer = timeout_s * 10; // Seconds
|
||||
|
||||
// Start timer
|
||||
*timer_ctrl |= (1 << TK1_MMIO_TIMER_CTRL_START_BIT);
|
||||
|
||||
// Acknowledge any stray touch events before waiting for real
|
||||
// touch
|
||||
*touch = 0;
|
||||
|
||||
// Blink until either the touch sensor has been touched or the
|
||||
// timer hits 0.
|
||||
while (!touched() && *timer_status != 0) {
|
||||
time = *timer;
|
||||
if (time % 2 == 0 && time != lasttime) {
|
||||
lasttime = time;
|
||||
ledon = !ledon;
|
||||
led_set(ledon ? color : LED_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore LED
|
||||
led_set(orig_color);
|
||||
|
||||
// Do we have a timeout?
|
||||
if (*timer_status == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop timer
|
||||
*timer_ctrl |= (1 << TK1_MMIO_TIMER_CTRL_STOP_BIT);
|
||||
|
||||
// Confirm touch event
|
||||
*touch = 0;
|
||||
|
||||
return true;
|
||||
}
|
53
hw/application_fpga/tkey-libs/libcrt0/crt0.S
Normal file
53
hw/application_fpga/tkey-libs/libcrt0/crt0.S
Normal file
@ -0,0 +1,53 @@
|
||||
// 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
|
116
hw/application_fpga/tkey-libs/monocypher/LICENSE
Normal file
116
hw/application_fpga/tkey-libs/monocypher/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
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/>
|
5
hw/application_fpga/tkey-libs/monocypher/README.md
Normal file
5
hw/application_fpga/tkey-libs/monocypher/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Monocypher
|
||||
|
||||
A ed25519 implementation from https://github.com/LoupVaillant/Monocypher
|
||||
|
||||
Small changes made for building.
|
500
hw/application_fpga/tkey-libs/monocypher/monocypher-ed25519.c
Normal file
500
hw/application_fpga/tkey-libs/monocypher/monocypher-ed25519.c
Normal file
@ -0,0 +1,500 @@
|
||||
// Monocypher version 4.0.2
|
||||
//
|
||||
// This file is dual-licensed. Choose whichever licence you want from
|
||||
// the two licences listed below.
|
||||
//
|
||||
// The first licence is a regular 2-clause BSD licence. The second licence
|
||||
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
||||
// to the public domain. The BSD licence serves as a fallback option.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
||||
//
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2017-2019, Loup Vaillant
|
||||
// All rights reserved.
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// Written in 2017-2019 by Loup Vaillant
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright
|
||||
// and related neighboring rights to this software to the public domain
|
||||
// worldwide. This software is distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along
|
||||
// with this software. If not, see
|
||||
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
#include "monocypher-ed25519.h"
|
||||
|
||||
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||
namespace MONOCYPHER_CPP_NAMESPACE {
|
||||
#endif
|
||||
|
||||
/////////////////
|
||||
/// Utilities ///
|
||||
/////////////////
|
||||
#define FOR(i, min, max) for (size_t i = min; i < max; i++)
|
||||
#define COPY(dst, src, size) FOR(_i_, 0, size) (dst)[_i_] = (src)[_i_]
|
||||
#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
|
||||
#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
|
||||
#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
|
||||
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
|
||||
typedef uint8_t u8;
|
||||
typedef uint64_t u64;
|
||||
|
||||
// Returns the smallest positive integer y such that
|
||||
// (x + y) % pow_2 == 0
|
||||
// Basically, it's how many bytes we need to add to "align" x.
|
||||
// Only works when pow_2 is a power of 2.
|
||||
// Note: we use ~x+1 instead of -x to avoid compiler warnings
|
||||
static size_t align(size_t x, size_t pow_2)
|
||||
{
|
||||
return (~x + 1) & (pow_2 - 1);
|
||||
}
|
||||
|
||||
static u64 load64_be(const u8 s[8])
|
||||
{
|
||||
return((u64)s[0] << 56)
|
||||
| ((u64)s[1] << 48)
|
||||
| ((u64)s[2] << 40)
|
||||
| ((u64)s[3] << 32)
|
||||
| ((u64)s[4] << 24)
|
||||
| ((u64)s[5] << 16)
|
||||
| ((u64)s[6] << 8)
|
||||
| (u64)s[7];
|
||||
}
|
||||
|
||||
static void store64_be(u8 out[8], u64 in)
|
||||
{
|
||||
out[0] = (in >> 56) & 0xff;
|
||||
out[1] = (in >> 48) & 0xff;
|
||||
out[2] = (in >> 40) & 0xff;
|
||||
out[3] = (in >> 32) & 0xff;
|
||||
out[4] = (in >> 24) & 0xff;
|
||||
out[5] = (in >> 16) & 0xff;
|
||||
out[6] = (in >> 8) & 0xff;
|
||||
out[7] = in & 0xff;
|
||||
}
|
||||
|
||||
static void load64_be_buf (u64 *dst, const u8 *src, size_t size) {
|
||||
FOR(i, 0, size) { dst[i] = load64_be(src + i*8); }
|
||||
}
|
||||
|
||||
///////////////
|
||||
/// SHA 512 ///
|
||||
///////////////
|
||||
static u64 rot(u64 x, int c ) { return (x >> c) | (x << (64 - c)); }
|
||||
static u64 ch (u64 x, u64 y, u64 z) { return (x & y) ^ (~x & z); }
|
||||
static u64 maj(u64 x, u64 y, u64 z) { return (x & y) ^ ( x & z) ^ (y & z); }
|
||||
static u64 big_sigma0(u64 x) { return rot(x, 28) ^ rot(x, 34) ^ rot(x, 39); }
|
||||
static u64 big_sigma1(u64 x) { return rot(x, 14) ^ rot(x, 18) ^ rot(x, 41); }
|
||||
static u64 lit_sigma0(u64 x) { return rot(x, 1) ^ rot(x, 8) ^ (x >> 7); }
|
||||
static u64 lit_sigma1(u64 x) { return rot(x, 19) ^ rot(x, 61) ^ (x >> 6); }
|
||||
|
||||
static const u64 K[80] = {
|
||||
0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
|
||||
0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
|
||||
0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
|
||||
0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
|
||||
0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
|
||||
0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
|
||||
0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
|
||||
0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
|
||||
0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
|
||||
0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
|
||||
0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
|
||||
0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
|
||||
0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
|
||||
0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
|
||||
0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
|
||||
0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
|
||||
0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
|
||||
0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
|
||||
0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
|
||||
0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817
|
||||
};
|
||||
|
||||
static void sha512_compress(crypto_sha512_ctx *ctx)
|
||||
{
|
||||
u64 a = ctx->hash[0]; u64 b = ctx->hash[1];
|
||||
u64 c = ctx->hash[2]; u64 d = ctx->hash[3];
|
||||
u64 e = ctx->hash[4]; u64 f = ctx->hash[5];
|
||||
u64 g = ctx->hash[6]; u64 h = ctx->hash[7];
|
||||
|
||||
FOR (j, 0, 16) {
|
||||
u64 in = K[j] + ctx->input[j];
|
||||
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
|
||||
u64 t2 = big_sigma0(a) + maj(a, b, c);
|
||||
h = g; g = f; f = e; e = d + t1;
|
||||
d = c; c = b; b = a; a = t1 + t2;
|
||||
}
|
||||
size_t i16 = 0;
|
||||
FOR(i, 1, 5) {
|
||||
i16 += 16;
|
||||
FOR (j, 0, 16) {
|
||||
ctx->input[j] += lit_sigma1(ctx->input[(j- 2) & 15]);
|
||||
ctx->input[j] += lit_sigma0(ctx->input[(j-15) & 15]);
|
||||
ctx->input[j] += ctx->input[(j- 7) & 15];
|
||||
u64 in = K[i16 + j] + ctx->input[j];
|
||||
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
|
||||
u64 t2 = big_sigma0(a) + maj(a, b, c);
|
||||
h = g; g = f; f = e; e = d + t1;
|
||||
d = c; c = b; b = a; a = t1 + t2;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->hash[0] += a; ctx->hash[1] += b;
|
||||
ctx->hash[2] += c; ctx->hash[3] += d;
|
||||
ctx->hash[4] += e; ctx->hash[5] += f;
|
||||
ctx->hash[6] += g; ctx->hash[7] += h;
|
||||
}
|
||||
|
||||
// Write 1 input byte
|
||||
static void sha512_set_input(crypto_sha512_ctx *ctx, u8 input)
|
||||
{
|
||||
size_t word = ctx->input_idx >> 3;
|
||||
size_t byte = ctx->input_idx & 7;
|
||||
ctx->input[word] |= (u64)input << (8 * (7 - byte));
|
||||
}
|
||||
|
||||
// Increment a 128-bit "word".
|
||||
static void sha512_incr(u64 x[2], u64 y)
|
||||
{
|
||||
x[1] += y;
|
||||
if (x[1] < y) {
|
||||
x[0]++;
|
||||
}
|
||||
}
|
||||
|
||||
void crypto_sha512_init(crypto_sha512_ctx *ctx)
|
||||
{
|
||||
ctx->hash[0] = 0x6a09e667f3bcc908;
|
||||
ctx->hash[1] = 0xbb67ae8584caa73b;
|
||||
ctx->hash[2] = 0x3c6ef372fe94f82b;
|
||||
ctx->hash[3] = 0xa54ff53a5f1d36f1;
|
||||
ctx->hash[4] = 0x510e527fade682d1;
|
||||
ctx->hash[5] = 0x9b05688c2b3e6c1f;
|
||||
ctx->hash[6] = 0x1f83d9abfb41bd6b;
|
||||
ctx->hash[7] = 0x5be0cd19137e2179;
|
||||
ctx->input_size[0] = 0;
|
||||
ctx->input_size[1] = 0;
|
||||
ctx->input_idx = 0;
|
||||
ZERO(ctx->input, 16);
|
||||
}
|
||||
|
||||
void crypto_sha512_update(crypto_sha512_ctx *ctx,
|
||||
const u8 *message, size_t message_size)
|
||||
{
|
||||
// Avoid undefined NULL pointer increments with empty messages
|
||||
if (message_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Align ourselves with word boundaries
|
||||
if ((ctx->input_idx & 7) != 0) {
|
||||
size_t nb_bytes = MIN(align(ctx->input_idx, 8), message_size);
|
||||
FOR (i, 0, nb_bytes) {
|
||||
sha512_set_input(ctx, message[i]);
|
||||
ctx->input_idx++;
|
||||
}
|
||||
message += nb_bytes;
|
||||
message_size -= nb_bytes;
|
||||
}
|
||||
|
||||
// Align ourselves with block boundaries
|
||||
if ((ctx->input_idx & 127) != 0) {
|
||||
size_t nb_words = MIN(align(ctx->input_idx, 128), message_size) >> 3;
|
||||
load64_be_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
|
||||
ctx->input_idx += nb_words << 3;
|
||||
message += nb_words << 3;
|
||||
message_size -= nb_words << 3;
|
||||
}
|
||||
|
||||
// Compress block if needed
|
||||
if (ctx->input_idx == 128) {
|
||||
sha512_incr(ctx->input_size, 1024); // size is in bits
|
||||
sha512_compress(ctx);
|
||||
ctx->input_idx = 0;
|
||||
ZERO(ctx->input, 16);
|
||||
}
|
||||
|
||||
// Process the message block by block
|
||||
FOR (i, 0, message_size >> 7) { // number of blocks
|
||||
load64_be_buf(ctx->input, message, 16);
|
||||
sha512_incr(ctx->input_size, 1024); // size is in bits
|
||||
sha512_compress(ctx);
|
||||
ctx->input_idx = 0;
|
||||
ZERO(ctx->input, 16);
|
||||
message += 128;
|
||||
}
|
||||
message_size &= 127;
|
||||
|
||||
if (message_size != 0) {
|
||||
// Remaining words
|
||||
size_t nb_words = message_size >> 3;
|
||||
load64_be_buf(ctx->input, message, nb_words);
|
||||
ctx->input_idx += nb_words << 3;
|
||||
message += nb_words << 3;
|
||||
message_size -= nb_words << 3;
|
||||
|
||||
// Remaining bytes
|
||||
FOR (i, 0, message_size) {
|
||||
sha512_set_input(ctx, message[i]);
|
||||
ctx->input_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void crypto_sha512_final(crypto_sha512_ctx *ctx, u8 hash[64])
|
||||
{
|
||||
// Add padding bit
|
||||
if (ctx->input_idx == 0) {
|
||||
ZERO(ctx->input, 16);
|
||||
}
|
||||
sha512_set_input(ctx, 128);
|
||||
|
||||
// Update size
|
||||
sha512_incr(ctx->input_size, ctx->input_idx * 8);
|
||||
|
||||
// Compress penultimate block (if any)
|
||||
if (ctx->input_idx > 111) {
|
||||
sha512_compress(ctx);
|
||||
ZERO(ctx->input, 14);
|
||||
}
|
||||
// Compress last block
|
||||
ctx->input[14] = ctx->input_size[0];
|
||||
ctx->input[15] = ctx->input_size[1];
|
||||
sha512_compress(ctx);
|
||||
|
||||
// Copy hash to output (big endian)
|
||||
FOR (i, 0, 8) {
|
||||
store64_be(hash + i*8, ctx->hash[i]);
|
||||
}
|
||||
|
||||
WIPE_CTX(ctx);
|
||||
}
|
||||
|
||||
void crypto_sha512(u8 hash[64], const u8 *message, size_t message_size)
|
||||
{
|
||||
crypto_sha512_ctx ctx;
|
||||
crypto_sha512_init (&ctx);
|
||||
crypto_sha512_update(&ctx, message, message_size);
|
||||
crypto_sha512_final (&ctx, hash);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
/// HMAC SHA 512 ///
|
||||
////////////////////
|
||||
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
|
||||
const u8 *key, size_t key_size)
|
||||
{
|
||||
// hash key if it is too long
|
||||
if (key_size > 128) {
|
||||
crypto_sha512(ctx->key, key, key_size);
|
||||
key = ctx->key;
|
||||
key_size = 64;
|
||||
}
|
||||
// Compute inner key: padded key XOR 0x36
|
||||
FOR (i, 0, key_size) { ctx->key[i] = key[i] ^ 0x36; }
|
||||
FOR (i, key_size, 128) { ctx->key[i] = 0x36; }
|
||||
// Start computing inner hash
|
||||
crypto_sha512_init (&ctx->ctx);
|
||||
crypto_sha512_update(&ctx->ctx, ctx->key, 128);
|
||||
}
|
||||
|
||||
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
|
||||
const u8 *message, size_t message_size)
|
||||
{
|
||||
crypto_sha512_update(&ctx->ctx, message, message_size);
|
||||
}
|
||||
|
||||
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, u8 hmac[64])
|
||||
{
|
||||
// Finish computing inner hash
|
||||
crypto_sha512_final(&ctx->ctx, hmac);
|
||||
// Compute outer key: padded key XOR 0x5c
|
||||
FOR (i, 0, 128) {
|
||||
ctx->key[i] ^= 0x36 ^ 0x5c;
|
||||
}
|
||||
// Compute outer hash
|
||||
crypto_sha512_init (&ctx->ctx);
|
||||
crypto_sha512_update(&ctx->ctx, ctx->key , 128);
|
||||
crypto_sha512_update(&ctx->ctx, hmac, 64);
|
||||
crypto_sha512_final (&ctx->ctx, hmac); // outer hash
|
||||
WIPE_CTX(ctx);
|
||||
}
|
||||
|
||||
void crypto_sha512_hmac(u8 hmac[64], const u8 *key, size_t key_size,
|
||||
const u8 *message, size_t message_size)
|
||||
{
|
||||
crypto_sha512_hmac_ctx ctx;
|
||||
crypto_sha512_hmac_init (&ctx, key, key_size);
|
||||
crypto_sha512_hmac_update(&ctx, message, message_size);
|
||||
crypto_sha512_hmac_final (&ctx, hmac);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
/// HKDF SHA 512 ///
|
||||
////////////////////
|
||||
void crypto_sha512_hkdf_expand(u8 *okm, size_t okm_size,
|
||||
const u8 *prk, size_t prk_size,
|
||||
const u8 *info, size_t info_size)
|
||||
{
|
||||
int not_first = 0;
|
||||
u8 ctr = 1;
|
||||
u8 blk[64];
|
||||
|
||||
while (okm_size > 0) {
|
||||
size_t out_size = MIN(okm_size, sizeof(blk));
|
||||
|
||||
crypto_sha512_hmac_ctx ctx;
|
||||
crypto_sha512_hmac_init(&ctx, prk , prk_size);
|
||||
if (not_first) {
|
||||
// For some reason HKDF uses some kind of CBC mode.
|
||||
// For some reason CTR mode alone wasn't enough.
|
||||
// Like what, they didn't trust HMAC in 2010? Really??
|
||||
crypto_sha512_hmac_update(&ctx, blk , sizeof(blk));
|
||||
}
|
||||
crypto_sha512_hmac_update(&ctx, info, info_size);
|
||||
crypto_sha512_hmac_update(&ctx, &ctr, 1);
|
||||
crypto_sha512_hmac_final(&ctx, blk);
|
||||
|
||||
COPY(okm, blk, out_size);
|
||||
|
||||
not_first = 1;
|
||||
okm += out_size;
|
||||
okm_size -= out_size;
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
|
||||
void crypto_sha512_hkdf(u8 *okm , size_t okm_size,
|
||||
const u8 *ikm , size_t ikm_size,
|
||||
const u8 *salt, size_t salt_size,
|
||||
const u8 *info, size_t info_size)
|
||||
{
|
||||
// Extract
|
||||
u8 prk[64];
|
||||
crypto_sha512_hmac(prk, salt, salt_size, ikm, ikm_size);
|
||||
|
||||
// Expand
|
||||
crypto_sha512_hkdf_expand(okm, okm_size, prk, sizeof(prk), info, info_size);
|
||||
}
|
||||
|
||||
///////////////
|
||||
/// Ed25519 ///
|
||||
///////////////
|
||||
void crypto_ed25519_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
|
||||
{
|
||||
u8 a[64];
|
||||
COPY(a, seed, 32); // a[ 0..31] = seed
|
||||
crypto_wipe(seed, 32);
|
||||
COPY(secret_key, a, 32); // secret key = seed
|
||||
crypto_sha512(a, a, 32); // a[ 0..31] = scalar
|
||||
crypto_eddsa_trim_scalar(a, a); // a[ 0..31] = trimmed scalar
|
||||
crypto_eddsa_scalarbase(public_key, a); // public key = [trimmed scalar]B
|
||||
COPY(secret_key + 32, public_key, 32); // secret key includes public half
|
||||
WIPE_BUFFER(a);
|
||||
}
|
||||
|
||||
static void hash_reduce(u8 h[32],
|
||||
const u8 *a, size_t a_size,
|
||||
const u8 *b, size_t b_size,
|
||||
const u8 *c, size_t c_size,
|
||||
const u8 *d, size_t d_size)
|
||||
{
|
||||
u8 hash[64];
|
||||
crypto_sha512_ctx ctx;
|
||||
crypto_sha512_init (&ctx);
|
||||
crypto_sha512_update(&ctx, a, a_size);
|
||||
crypto_sha512_update(&ctx, b, b_size);
|
||||
crypto_sha512_update(&ctx, c, c_size);
|
||||
crypto_sha512_update(&ctx, d, d_size);
|
||||
crypto_sha512_final (&ctx, hash);
|
||||
crypto_eddsa_reduce(h, hash);
|
||||
}
|
||||
|
||||
static void ed25519_dom_sign(u8 signature [64], const u8 secret_key[32],
|
||||
const u8 *dom, size_t dom_size,
|
||||
const u8 *message, size_t message_size)
|
||||
{
|
||||
u8 a[64]; // secret scalar and prefix
|
||||
u8 r[32]; // secret deterministic "random" nonce
|
||||
u8 h[32]; // publically verifiable hash of the message (not wiped)
|
||||
u8 R[32]; // first half of the signature (allows overlapping inputs)
|
||||
const u8 *pk = secret_key + 32;
|
||||
|
||||
crypto_sha512(a, secret_key, 32);
|
||||
crypto_eddsa_trim_scalar(a, a);
|
||||
hash_reduce(r, dom, dom_size, a + 32, 32, message, message_size, 0, 0);
|
||||
crypto_eddsa_scalarbase(R, r);
|
||||
hash_reduce(h, dom, dom_size, R, 32, pk, 32, message, message_size);
|
||||
COPY(signature, R, 32);
|
||||
crypto_eddsa_mul_add(signature + 32, h, a, r);
|
||||
|
||||
WIPE_BUFFER(a);
|
||||
WIPE_BUFFER(r);
|
||||
}
|
||||
|
||||
void crypto_ed25519_sign(u8 signature [64], const u8 secret_key[64],
|
||||
const u8 *message, size_t message_size)
|
||||
{
|
||||
ed25519_dom_sign(signature, secret_key, 0, 0, message, message_size);
|
||||
}
|
||||
|
||||
int crypto_ed25519_check(const u8 signature[64], const u8 public_key[32],
|
||||
const u8 *msg, size_t msg_size)
|
||||
{
|
||||
u8 h_ram[32];
|
||||
hash_reduce(h_ram, signature, 32, public_key, 32, msg, msg_size, 0, 0);
|
||||
return crypto_eddsa_check_equation(signature, public_key, h_ram);
|
||||
}
|
||||
|
||||
static const u8 domain[34] = "SigEd25519 no Ed25519 collisions\1";
|
||||
|
||||
void crypto_ed25519_ph_sign(uint8_t signature[64], const uint8_t secret_key[64],
|
||||
const uint8_t message_hash[64])
|
||||
{
|
||||
ed25519_dom_sign(signature, secret_key, domain, sizeof(domain),
|
||||
message_hash, 64);
|
||||
}
|
||||
|
||||
int crypto_ed25519_ph_check(const uint8_t sig[64], const uint8_t pk[32],
|
||||
const uint8_t msg_hash[64])
|
||||
{
|
||||
u8 h_ram[32];
|
||||
hash_reduce(h_ram, domain, sizeof(domain), sig, 32, pk, 32, msg_hash, 64);
|
||||
return crypto_eddsa_check_equation(sig, pk, h_ram);
|
||||
}
|
||||
|
||||
|
||||
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||
}
|
||||
#endif
|
140
hw/application_fpga/tkey-libs/monocypher/monocypher-ed25519.h
Normal file
140
hw/application_fpga/tkey-libs/monocypher/monocypher-ed25519.h
Normal file
@ -0,0 +1,140 @@
|
||||
// Monocypher version 4.0.2
|
||||
//
|
||||
// This file is dual-licensed. Choose whichever licence you want from
|
||||
// the two licences listed below.
|
||||
//
|
||||
// The first licence is a regular 2-clause BSD licence. The second licence
|
||||
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
||||
// to the public domain. The BSD licence serves as a fallback option.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
||||
//
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2017-2019, Loup Vaillant
|
||||
// All rights reserved.
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// Written in 2017-2019 by Loup Vaillant
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright
|
||||
// and related neighboring rights to this software to the public domain
|
||||
// worldwide. This software is distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along
|
||||
// with this software. If not, see
|
||||
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
#ifndef ED25519_H
|
||||
#define ED25519_H
|
||||
|
||||
#include "monocypher.h"
|
||||
|
||||
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||
namespace MONOCYPHER_CPP_NAMESPACE {
|
||||
#elif defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////
|
||||
/// Type definitions ///
|
||||
////////////////////////
|
||||
|
||||
// Do not rely on the size or content on any of those types,
|
||||
// they may change without notice.
|
||||
typedef struct {
|
||||
uint64_t hash[8];
|
||||
uint64_t input[16];
|
||||
uint64_t input_size[2];
|
||||
size_t input_idx;
|
||||
} crypto_sha512_ctx;
|
||||
|
||||
typedef struct {
|
||||
uint8_t key[128];
|
||||
crypto_sha512_ctx ctx;
|
||||
} crypto_sha512_hmac_ctx;
|
||||
|
||||
|
||||
// SHA 512
|
||||
// -------
|
||||
void crypto_sha512_init (crypto_sha512_ctx *ctx);
|
||||
void crypto_sha512_update(crypto_sha512_ctx *ctx,
|
||||
const uint8_t *message, size_t message_size);
|
||||
void crypto_sha512_final (crypto_sha512_ctx *ctx, uint8_t hash[64]);
|
||||
void crypto_sha512(uint8_t hash[64],
|
||||
const uint8_t *message, size_t message_size);
|
||||
|
||||
// SHA 512 HMAC
|
||||
// ------------
|
||||
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
|
||||
const uint8_t *key, size_t key_size);
|
||||
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
|
||||
const uint8_t *message, size_t message_size);
|
||||
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, uint8_t hmac[64]);
|
||||
void crypto_sha512_hmac(uint8_t hmac[64],
|
||||
const uint8_t *key , size_t key_size,
|
||||
const uint8_t *message, size_t message_size);
|
||||
|
||||
// SHA 512 HKDF
|
||||
// ------------
|
||||
void crypto_sha512_hkdf_expand(uint8_t *okm, size_t okm_size,
|
||||
const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size);
|
||||
void crypto_sha512_hkdf(uint8_t *okm , size_t okm_size,
|
||||
const uint8_t *ikm , size_t ikm_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
const uint8_t *info, size_t info_size);
|
||||
|
||||
// Ed25519
|
||||
// -------
|
||||
// Signatures (EdDSA with curve25519 + SHA-512)
|
||||
// --------------------------------------------
|
||||
void crypto_ed25519_key_pair(uint8_t secret_key[64],
|
||||
uint8_t public_key[32],
|
||||
uint8_t seed[32]);
|
||||
void crypto_ed25519_sign(uint8_t signature [64],
|
||||
const uint8_t secret_key[64],
|
||||
const uint8_t *message, size_t message_size);
|
||||
int crypto_ed25519_check(const uint8_t signature [64],
|
||||
const uint8_t public_key[32],
|
||||
const uint8_t *message, size_t message_size);
|
||||
|
||||
// Pre-hash variants
|
||||
void crypto_ed25519_ph_sign(uint8_t signature [64],
|
||||
const uint8_t secret_key [64],
|
||||
const uint8_t message_hash[64]);
|
||||
int crypto_ed25519_ph_check(const uint8_t signature [64],
|
||||
const uint8_t public_key [32],
|
||||
const uint8_t message_hash[64]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ED25519_H
|
2956
hw/application_fpga/tkey-libs/monocypher/monocypher.c
Normal file
2956
hw/application_fpga/tkey-libs/monocypher/monocypher.c
Normal file
File diff suppressed because it is too large
Load Diff
321
hw/application_fpga/tkey-libs/monocypher/monocypher.h
Normal file
321
hw/application_fpga/tkey-libs/monocypher/monocypher.h
Normal file
@ -0,0 +1,321 @@
|
||||
// Monocypher version 4.0.2
|
||||
//
|
||||
// This file is dual-licensed. Choose whichever licence you want from
|
||||
// the two licences listed below.
|
||||
//
|
||||
// The first licence is a regular 2-clause BSD licence. The second licence
|
||||
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
||||
// to the public domain. The BSD licence serves as a fallback option.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
||||
//
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2017-2019, Loup Vaillant
|
||||
// All rights reserved.
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// Written in 2017-2019 by Loup Vaillant
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright
|
||||
// and related neighboring rights to this software to the public domain
|
||||
// worldwide. This software is distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along
|
||||
// with this software. If not, see
|
||||
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
#ifndef MONOCYPHER_H
|
||||
#define MONOCYPHER_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||
namespace MONOCYPHER_CPP_NAMESPACE {
|
||||
#elif defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Constant time comparisons
|
||||
// -------------------------
|
||||
|
||||
// Return 0 if a and b are equal, -1 otherwise
|
||||
int crypto_verify16(const uint8_t a[16], const uint8_t b[16]);
|
||||
int crypto_verify32(const uint8_t a[32], const uint8_t b[32]);
|
||||
int crypto_verify64(const uint8_t a[64], const uint8_t b[64]);
|
||||
|
||||
|
||||
// Erase sensitive data
|
||||
// --------------------
|
||||
void crypto_wipe(void *secret, size_t size);
|
||||
|
||||
|
||||
// Authenticated encryption
|
||||
// ------------------------
|
||||
void crypto_aead_lock(uint8_t *cipher_text,
|
||||
uint8_t mac [16],
|
||||
const uint8_t key [32],
|
||||
const uint8_t nonce[24],
|
||||
const uint8_t *ad, size_t ad_size,
|
||||
const uint8_t *plain_text, size_t text_size);
|
||||
int crypto_aead_unlock(uint8_t *plain_text,
|
||||
const uint8_t mac [16],
|
||||
const uint8_t key [32],
|
||||
const uint8_t nonce[24],
|
||||
const uint8_t *ad, size_t ad_size,
|
||||
const uint8_t *cipher_text, size_t text_size);
|
||||
|
||||
// Authenticated stream
|
||||
// --------------------
|
||||
typedef struct {
|
||||
uint64_t counter;
|
||||
uint8_t key[32];
|
||||
uint8_t nonce[8];
|
||||
} crypto_aead_ctx;
|
||||
|
||||
void crypto_aead_init_x(crypto_aead_ctx *ctx,
|
||||
const uint8_t key[32], const uint8_t nonce[24]);
|
||||
void crypto_aead_init_djb(crypto_aead_ctx *ctx,
|
||||
const uint8_t key[32], const uint8_t nonce[8]);
|
||||
void crypto_aead_init_ietf(crypto_aead_ctx *ctx,
|
||||
const uint8_t key[32], const uint8_t nonce[12]);
|
||||
|
||||
void crypto_aead_write(crypto_aead_ctx *ctx,
|
||||
uint8_t *cipher_text,
|
||||
uint8_t mac[16],
|
||||
const uint8_t *ad , size_t ad_size,
|
||||
const uint8_t *plain_text, size_t text_size);
|
||||
int crypto_aead_read(crypto_aead_ctx *ctx,
|
||||
uint8_t *plain_text,
|
||||
const uint8_t mac[16],
|
||||
const uint8_t *ad , size_t ad_size,
|
||||
const uint8_t *cipher_text, size_t text_size);
|
||||
|
||||
|
||||
// General purpose hash (BLAKE2b)
|
||||
// ------------------------------
|
||||
|
||||
// Direct interface
|
||||
void crypto_blake2b(uint8_t *hash, size_t hash_size,
|
||||
const uint8_t *message, size_t message_size);
|
||||
|
||||
void crypto_blake2b_keyed(uint8_t *hash, size_t hash_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *message, size_t message_size);
|
||||
|
||||
// Incremental interface
|
||||
typedef struct {
|
||||
// Do not rely on the size or contents of this type,
|
||||
// for they may change without notice.
|
||||
uint64_t hash[8];
|
||||
uint64_t input_offset[2];
|
||||
uint64_t input[16];
|
||||
size_t input_idx;
|
||||
size_t hash_size;
|
||||
} crypto_blake2b_ctx;
|
||||
|
||||
void crypto_blake2b_init(crypto_blake2b_ctx *ctx, size_t hash_size);
|
||||
void crypto_blake2b_keyed_init(crypto_blake2b_ctx *ctx, size_t hash_size,
|
||||
const uint8_t *key, size_t key_size);
|
||||
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
|
||||
const uint8_t *message, size_t message_size);
|
||||
void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *hash);
|
||||
|
||||
|
||||
// Password key derivation (Argon2)
|
||||
// --------------------------------
|
||||
#define CRYPTO_ARGON2_D 0
|
||||
#define CRYPTO_ARGON2_I 1
|
||||
#define CRYPTO_ARGON2_ID 2
|
||||
|
||||
typedef struct {
|
||||
uint32_t algorithm; // Argon2d, Argon2i, Argon2id
|
||||
uint32_t nb_blocks; // memory hardness, >= 8 * nb_lanes
|
||||
uint32_t nb_passes; // CPU hardness, >= 1 (>= 3 recommended for Argon2i)
|
||||
uint32_t nb_lanes; // parallelism level (single threaded anyway)
|
||||
} crypto_argon2_config;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *pass;
|
||||
const uint8_t *salt;
|
||||
uint32_t pass_size;
|
||||
uint32_t salt_size; // 16 bytes recommended
|
||||
} crypto_argon2_inputs;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *key; // may be NULL if no key
|
||||
const uint8_t *ad; // may be NULL if no additional data
|
||||
uint32_t key_size; // 0 if no key (32 bytes recommended otherwise)
|
||||
uint32_t ad_size; // 0 if no additional data
|
||||
} crypto_argon2_extras;
|
||||
|
||||
extern const crypto_argon2_extras crypto_argon2_no_extras;
|
||||
|
||||
void crypto_argon2(uint8_t *hash, uint32_t hash_size, void *work_area,
|
||||
crypto_argon2_config config,
|
||||
crypto_argon2_inputs inputs,
|
||||
crypto_argon2_extras extras);
|
||||
|
||||
|
||||
// Key exchange (X-25519)
|
||||
// ----------------------
|
||||
|
||||
// Shared secrets are not quite random.
|
||||
// Hash them to derive an actual shared key.
|
||||
void crypto_x25519_public_key(uint8_t public_key[32],
|
||||
const uint8_t secret_key[32]);
|
||||
void crypto_x25519(uint8_t raw_shared_secret[32],
|
||||
const uint8_t your_secret_key [32],
|
||||
const uint8_t their_public_key [32]);
|
||||
|
||||
// Conversion to EdDSA
|
||||
void crypto_x25519_to_eddsa(uint8_t eddsa[32], const uint8_t x25519[32]);
|
||||
|
||||
// scalar "division"
|
||||
// Used for OPRF. Be aware that exponential blinding is less secure
|
||||
// than Diffie-Hellman key exchange.
|
||||
void crypto_x25519_inverse(uint8_t blind_salt [32],
|
||||
const uint8_t private_key[32],
|
||||
const uint8_t curve_point[32]);
|
||||
|
||||
// "Dirty" versions of x25519_public_key().
|
||||
// Use with crypto_elligator_rev().
|
||||
// Leaks 3 bits of the private key.
|
||||
void crypto_x25519_dirty_small(uint8_t pk[32], const uint8_t sk[32]);
|
||||
void crypto_x25519_dirty_fast (uint8_t pk[32], const uint8_t sk[32]);
|
||||
|
||||
|
||||
// Signatures
|
||||
// ----------
|
||||
|
||||
// EdDSA with curve25519 + BLAKE2b
|
||||
void crypto_eddsa_key_pair(uint8_t secret_key[64],
|
||||
uint8_t public_key[32],
|
||||
uint8_t seed[32]);
|
||||
void crypto_eddsa_sign(uint8_t signature [64],
|
||||
const uint8_t secret_key[64],
|
||||
const uint8_t *message, size_t message_size);
|
||||
int crypto_eddsa_check(const uint8_t signature [64],
|
||||
const uint8_t public_key[32],
|
||||
const uint8_t *message, size_t message_size);
|
||||
|
||||
// Conversion to X25519
|
||||
void crypto_eddsa_to_x25519(uint8_t x25519[32], const uint8_t eddsa[32]);
|
||||
|
||||
// EdDSA building blocks
|
||||
void crypto_eddsa_trim_scalar(uint8_t out[32], const uint8_t in[32]);
|
||||
void crypto_eddsa_reduce(uint8_t reduced[32], const uint8_t expanded[64]);
|
||||
void crypto_eddsa_mul_add(uint8_t r[32],
|
||||
const uint8_t a[32],
|
||||
const uint8_t b[32],
|
||||
const uint8_t c[32]);
|
||||
void crypto_eddsa_scalarbase(uint8_t point[32], const uint8_t scalar[32]);
|
||||
int crypto_eddsa_check_equation(const uint8_t signature[64],
|
||||
const uint8_t public_key[32],
|
||||
const uint8_t h_ram[32]);
|
||||
|
||||
|
||||
// Chacha20
|
||||
// --------
|
||||
|
||||
// Specialised hash.
|
||||
// Used to hash X25519 shared secrets.
|
||||
void crypto_chacha20_h(uint8_t out[32],
|
||||
const uint8_t key[32],
|
||||
const uint8_t in [16]);
|
||||
|
||||
// Unauthenticated stream cipher.
|
||||
// Don't forget to add authentication.
|
||||
uint64_t crypto_chacha20_djb(uint8_t *cipher_text,
|
||||
const uint8_t *plain_text,
|
||||
size_t text_size,
|
||||
const uint8_t key[32],
|
||||
const uint8_t nonce[8],
|
||||
uint64_t ctr);
|
||||
uint32_t crypto_chacha20_ietf(uint8_t *cipher_text,
|
||||
const uint8_t *plain_text,
|
||||
size_t text_size,
|
||||
const uint8_t key[32],
|
||||
const uint8_t nonce[12],
|
||||
uint32_t ctr);
|
||||
uint64_t crypto_chacha20_x(uint8_t *cipher_text,
|
||||
const uint8_t *plain_text,
|
||||
size_t text_size,
|
||||
const uint8_t key[32],
|
||||
const uint8_t nonce[24],
|
||||
uint64_t ctr);
|
||||
|
||||
|
||||
// Poly 1305
|
||||
// ---------
|
||||
|
||||
// This is a *one time* authenticator.
|
||||
// Disclosing the mac reveals the key.
|
||||
// See crypto_lock() on how to use it properly.
|
||||
|
||||
// Direct interface
|
||||
void crypto_poly1305(uint8_t mac[16],
|
||||
const uint8_t *message, size_t message_size,
|
||||
const uint8_t key[32]);
|
||||
|
||||
// Incremental interface
|
||||
typedef struct {
|
||||
// Do not rely on the size or contents of this type,
|
||||
// for they may change without notice.
|
||||
uint8_t c[16]; // chunk of the message
|
||||
size_t c_idx; // How many bytes are there in the chunk.
|
||||
uint32_t r [4]; // constant multiplier (from the secret key)
|
||||
uint32_t pad[4]; // random number added at the end (from the secret key)
|
||||
uint32_t h [5]; // accumulated hash
|
||||
} crypto_poly1305_ctx;
|
||||
|
||||
void crypto_poly1305_init (crypto_poly1305_ctx *ctx, const uint8_t key[32]);
|
||||
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
|
||||
const uint8_t *message, size_t message_size);
|
||||
void crypto_poly1305_final (crypto_poly1305_ctx *ctx, uint8_t mac[16]);
|
||||
|
||||
|
||||
// Elligator 2
|
||||
// -----------
|
||||
|
||||
// Elligator mappings proper
|
||||
void crypto_elligator_map(uint8_t curve [32], const uint8_t hidden[32]);
|
||||
int crypto_elligator_rev(uint8_t hidden[32], const uint8_t curve [32],
|
||||
uint8_t tweak);
|
||||
|
||||
// Easy to use key pair generation
|
||||
void crypto_elligator_key_pair(uint8_t hidden[32], uint8_t secret_key[32],
|
||||
uint8_t seed[32]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MONOCYPHER_H
|
92
hw/application_fpga/tkey-libs/tools/spdx-ensure
Executable file
92
hw/application_fpga/tkey-libs/tools/spdx-ensure
Executable file
@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
# SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
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/
|
||||
)
|
||||
|
||||
missingok_files=(
|
||||
.clang-format
|
||||
.editorconfig
|
||||
.gitignore
|
||||
LICENSE
|
||||
Makefile
|
||||
README.md
|
||||
README-DIST.txt
|
||||
RELEASE.md
|
||||
example-app/Makefile
|
||||
monocypher/LICENSE
|
||||
monocypher/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"
|
Loading…
x
Reference in New Issue
Block a user