Compare commits
4 Commits
simplify_b
...
fido2_on_u
Author | SHA1 | Date | |
---|---|---|---|
9dfc3d49e8 | |||
3487895e2d | |||
6335f16874 | |||
82551c0b1c |
3
.gitignore
vendored
3
.gitignore
vendored
@ -34,8 +34,7 @@
|
|||||||
*.app
|
*.app
|
||||||
*.i*86
|
*.i*86
|
||||||
*.x86_64
|
*.x86_64
|
||||||
targets/*/*.hex
|
*.hex
|
||||||
targets/*/*.sha2
|
|
||||||
|
|
||||||
# Debug files
|
# Debug files
|
||||||
*.dSYM/
|
*.dSYM/
|
||||||
|
@ -6,15 +6,14 @@ addons:
|
|||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
packages:
|
packages:
|
||||||
- gcc-8
|
- gcc-7
|
||||||
- cppcheck
|
- cppcheck
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
|
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
|
||||||
- sudo apt-get update -q
|
- sudo apt-get update -q
|
||||||
- sudo apt-get install -y gcc-arm-embedded python3-venv
|
- sudo apt-get install -y gcc-arm-embedded
|
||||||
|
- sudo apt-get install -y python3-venv
|
||||||
script:
|
script:
|
||||||
- export CC=gcc-8
|
- export CC=gcc-7
|
||||||
- pyenv shell 3.6.7
|
- pyenv shell 3.6.7
|
||||||
- make travis
|
- make travis
|
||||||
|
61
Dockerfile
61
Dockerfile
@ -1,38 +1,33 @@
|
|||||||
FROM debian:9.11-slim
|
FROM debian:stretch-slim
|
||||||
MAINTAINER SoloKeys <hello@solokeys.com>
|
MAINTAINER SoloKeys <hello@solokeys.com>
|
||||||
|
|
||||||
# Install necessary packages
|
RUN apt-get update -qq
|
||||||
RUN apt-get update \
|
RUN apt-get install -qq bzip2 git make wget >/dev/null
|
||||||
&& apt-get install -y --no-install-recommends \
|
|
||||||
ca-certificates \
|
|
||||||
make \
|
|
||||||
wget \
|
|
||||||
bzip2 \
|
|
||||||
git \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install ARM compiler
|
# 1. ARM GCC: for compilation
|
||||||
RUN set -eux; \
|
RUN wget -q -O gcc.tar.bz2 https://developer.arm.com/-/media/Files/downloads/gnu-rm/8-2018q4/gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2?revision=d830f9dd-cd4f-406d-8672-cca9210dd220?product=GNU%20Arm%20Embedded%20Toolchain,64-bit,,Linux,8-2018-q4-major
|
||||||
url="https://developer.arm.com/-/media/Files/downloads/gnu-rm/8-2019q3/RC1.1/gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2?revision=c34d758a-be0c-476e-a2de-af8c6e16a8a2?product=GNU%20Arm%20Embedded%20Toolchain,64-bit,,Linux,8-2019-q3-update"; \
|
# from website
|
||||||
wget -O gcc.tar.bz2 "$url"; \
|
RUN echo "f55f90d483ddb3bcf4dae5882c2094cd gcc.tar.bz2" > gcc.md5
|
||||||
echo "6341f11972dac8de185646d0fbd73bfc gcc.tar.bz2" | md5sum -c -; \
|
RUN md5sum -c gcc.md5
|
||||||
echo "b50b02b0a16e5aad8620e9d7c31110ef285c1dde28980b1a9448b764d77d8f92 gcc.tar.bz2" | sha256sum -c -; \
|
# self-generated
|
||||||
tar -C /opt -xf gcc.tar.bz2; \
|
RUN echo "fb31fbdfe08406ece43eef5df623c0b2deb8b53e405e2c878300f7a1f303ee52 gcc.tar.bz2" > gcc.sha256
|
||||||
rm gcc.tar.bz2;
|
RUN sha256sum -c gcc.sha256
|
||||||
|
RUN tar -C /opt -xf gcc.tar.bz2
|
||||||
|
|
||||||
# Python3.7: for solo-python (merging etc.)
|
# 2. Python3.7: for solo-python (merging etc.)
|
||||||
RUN set -eux; \
|
RUN wget -q -O miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh
|
||||||
url="https://repo.anaconda.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh"; \
|
# from website
|
||||||
wget -O miniconda.sh "$url"; \
|
RUN echo "866ae9dff53ad0874e1d1a60b1ad1ef8 miniconda.sh" > miniconda.md5
|
||||||
echo "866ae9dff53ad0874e1d1a60b1ad1ef8 miniconda.sh" | md5sum -c -; \
|
RUN md5sum -c miniconda.md5
|
||||||
echo "e5e5b4cd2a918e0e96b395534222773f7241dc59d776db1b9f7fedfcb489157a miniconda.sh" | sha256sum -c -; \
|
# self-generated
|
||||||
bash ./miniconda.sh -b -p /opt/conda; \
|
RUN echo "e5e5b4cd2a918e0e96b395534222773f7241dc59d776db1b9f7fedfcb489157a miniconda.sh" > miniconda.sha256
|
||||||
ln -s /opt/conda/bin/python /usr/local/bin/python3; \
|
RUN sha256sum -c miniconda.sha256
|
||||||
ln -s /opt/conda/bin/python /usr/local/bin/python; \
|
|
||||||
ln -s /opt/conda/bin/pip /usr/local/bin/pip3; \
|
|
||||||
ln -s /opt/conda/bin/pip /usr/local/bin/pip; \
|
|
||||||
rm miniconda.sh; \
|
|
||||||
pip install -U pip
|
|
||||||
|
|
||||||
# solo-python (Python3.7 script for merging etc.)
|
RUN bash ./miniconda.sh -b -p /opt/conda
|
||||||
RUN pip install -U solo-python
|
RUN ln -s /opt/conda/bin/python /usr/local/bin/python3
|
||||||
|
RUN ln -s /opt/conda/bin/python /usr/local/bin/python
|
||||||
|
RUN ln -s /opt/conda/bin/pip /usr/local/bin/pip3
|
||||||
|
RUN ln -s /opt/conda/bin/pip /usr/local/bin/pip
|
||||||
|
|
||||||
|
# 3. Source code
|
||||||
|
RUN git clone --recurse-submodules https://github.com/solokeys/solo /solo --config core.autocrlf=input
|
||||||
|
48
Makefile
48
Makefile
@ -23,8 +23,8 @@ else
|
|||||||
endif
|
endif
|
||||||
LDFLAGS += $(LIBCBOR)
|
LDFLAGS += $(LIBCBOR)
|
||||||
|
|
||||||
|
VERSION:=$(shell git describe --abbrev=0 )
|
||||||
VERSION_FULL:=$(shell git describe)
|
VERSION_FULL:=$(shell git describe)
|
||||||
VERSION:=$(shell python -c 'print("$(VERSION_FULL)".split("-")[0])')
|
|
||||||
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
|
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
|
||||||
VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
|
VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
|
||||||
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
|
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
|
||||||
@ -62,7 +62,7 @@ test: venv
|
|||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
$(MAKE) -C . main
|
$(MAKE) -C . main
|
||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
$(MAKE) -C ./targets/stm32l432 test PREFIX=$(PREFIX) "VENV=$(VENV)" VERSION_FULL=${VERSION_FULL}
|
$(MAKE) -C ./targets/stm32l432 test PREFIX=$(PREFIX) "VENV=$(VENV)"
|
||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
$(MAKE) cppcheck
|
$(MAKE) cppcheck
|
||||||
|
|
||||||
@ -88,30 +88,18 @@ wink: venv
|
|||||||
fido2-test: venv
|
fido2-test: venv
|
||||||
venv/bin/python tools/ctap_test.py
|
venv/bin/python tools/ctap_test.py
|
||||||
|
|
||||||
update:
|
DOCKER_IMAGE := "solokeys/solo-firmware:local"
|
||||||
git fetch --tags
|
SOLO_VERSIONISH := "master"
|
||||||
git checkout master
|
docker-build:
|
||||||
git rebase origin/master
|
docker build -t $(DOCKER_IMAGE) .
|
||||||
git submodule update --init --recursive
|
|
||||||
|
|
||||||
DOCKER_TOOLCHAIN_IMAGE := "solokeys/solo-firmware-toolchain"
|
|
||||||
|
|
||||||
docker-build-toolchain:
|
|
||||||
docker build -t $(DOCKER_TOOLCHAIN_IMAGE) .
|
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION}
|
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}
|
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}.${VERSION_MIN}
|
|
||||||
|
|
||||||
uncached-docker-build-toolchain:
|
|
||||||
docker build --no-cache -t $(DOCKER_TOOLCHAIN_IMAGE) .
|
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION}
|
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}
|
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}.${VERSION_MIN}
|
|
||||||
|
|
||||||
docker-build-all:
|
|
||||||
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
||||||
-v "$(CURDIR):/solo" \
|
-v "$(CURDIR)/in-docker-build.sh:/in-docker-build.sh" \
|
||||||
$(DOCKER_TOOLCHAIN_IMAGE) "solo/in-docker-build.sh" ${VERSION_FULL}
|
$(DOCKER_IMAGE) "./in-docker-build.sh" $(SOLO_VERSIONISH)
|
||||||
|
uncached-docker-build:
|
||||||
|
docker build --no-cache -t $(DOCKER_IMAGE) .
|
||||||
|
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
||||||
|
-v "$(CURDIR)/in-docker-build.sh:/in-docker-build.sh" \
|
||||||
|
$(DOCKER_IMAGE) "./in-docker-build.sh" $(SOLO_VERSIONISH)
|
||||||
|
|
||||||
CPPCHECK_FLAGS=--quiet --error-exitcode=2
|
CPPCHECK_FLAGS=--quiet --error-exitcode=2
|
||||||
|
|
||||||
@ -132,14 +120,6 @@ clean:
|
|||||||
full-clean: clean
|
full-clean: clean
|
||||||
rm -rf venv
|
rm -rf venv
|
||||||
|
|
||||||
test-docker:
|
|
||||||
rm -rf builds/*
|
|
||||||
$(MAKE) uncached-docker-build-toolchain
|
|
||||||
# Check if there are 4 docker images/tas named "solokeys/solo-firmware-toolchain"
|
|
||||||
NTAGS=$$(docker images | grep -c "solokeys/solo-firmware-toolchain") && [ $$NTAGS -eq 4 ]
|
|
||||||
$(MAKE) docker-build-all
|
|
||||||
|
|
||||||
travis:
|
travis:
|
||||||
$(MAKE) test VENV=". ../../venv/bin/activate;"
|
$(MAKE) test VENV=". ../../venv/bin/activate;"
|
||||||
$(MAKE) test-docker
|
$(MAKE) black
|
||||||
$(MAKE) black
|
|
||||||
|
67
README.md
67
README.md
@ -1,3 +1,9 @@
|
|||||||
|
**NEW!** We launched a new tiny security key called Somu, it's live on Crowd Supply and you can [pre-order it now](https://solokeys.com/somu)!
|
||||||
|
|
||||||
|
[<img src="https://miro.medium.com/max/1400/1*PnzCPLqq_5nt1gjgSEY2LQ.png" width="600">](https://solokeys.com/somu)
|
||||||
|
|
||||||
|
Somu is the micro version of Solo. We were inspired to make a secure Tomu, so we took its tiny form factor, we added the secure microcontroller and firmware of Solo, et voilà! Here we have Somu.
|
||||||
|
|
||||||
[](https://update.solokeys.com/)
|
[](https://update.solokeys.com/)
|
||||||
[](https://keybase.io/team/solokeys.public)
|
[](https://keybase.io/team/solokeys.public)
|
||||||
[](https://travis-ci.com/solokeys/solo)
|
[](https://travis-ci.com/solokeys/solo)
|
||||||
@ -32,58 +38,10 @@ Check out [solokeys.com](https://solokeys.com), for options on where to buy Solo
|
|||||||
|
|
||||||
If you have a Solo for Hacker, here's how you can load your own code on it. You can find more details, including how to permanently lock it, in our [documentation](https://docs.solokeys.io/solo/building/). We support Python3.
|
If you have a Solo for Hacker, here's how you can load your own code on it. You can find more details, including how to permanently lock it, in our [documentation](https://docs.solokeys.io/solo/building/). We support Python3.
|
||||||
|
|
||||||
For example, if you want to turn off any blue light emission, you can edit [`led_rgb()`](https://github.com/solokeys/solo/blob/master/targets/stm32l432/src/app.h#L48) and change `LED_INIT_VALUE`
|
|
||||||
to be a different hex color.
|
|
||||||
|
|
||||||
Then recompile, load your new firmware, and enjoy a different LED color Solo.
|
|
||||||
|
|
||||||
In the Hacker version, hardware is the same but the firmware is unlocked, so you can 1) load an unsigned application, or 2) entirely reflash the key. By contrast, in a regular Solo you can only upgrade to a firmware signed by SoloKeys, and flash is locked and debug disabled permanently.
|
|
||||||
|
|
||||||
Hacker Solo isn't really secure so you should only use it for development. An attacker with physical access to a Solo for Hacker can reflash it following the steps above, and even a malware on your computer could possibly reflash it.
|
|
||||||
|
|
||||||
## Checking out the code
|
|
||||||
```bash
|
```bash
|
||||||
git clone --recurse-submodules https://github.com/solokeys/solo
|
git clone --recurse-submodules https://github.com/solokeys/solo
|
||||||
cd solo
|
cd solo
|
||||||
```
|
|
||||||
|
|
||||||
If you forgot the `--recurse-submodules` while cloning, simply run `git submodule update --init --recursive`.
|
|
||||||
|
|
||||||
`make update` will also checkout the latest code on `master` and submodules.
|
|
||||||
|
|
||||||
## Checking out the code to build a specific version
|
|
||||||
|
|
||||||
You can checkout the code to build a specific version of the firmware with:
|
|
||||||
```
|
|
||||||
VERSION_TO_BUILD=2.5.3
|
|
||||||
git fetch --tags
|
|
||||||
git checkout ${VERSION_TO_BUILD}
|
|
||||||
git submodule update --init --recursive
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installing the toolchain
|
|
||||||
|
|
||||||
In order to compile ARM code, you need the ARM compiler and other things like bundling bootloader and firmware require the `solo-python` python package. Check our [documentation](https://docs.solokeys.io/solo/) for details
|
|
||||||
|
|
||||||
## Installing the toolkit and compiling in Docker
|
|
||||||
Alternatively, you can use Docker to create a container with the toolchain.
|
|
||||||
You can run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build the toolchain container
|
|
||||||
make docker-build-toolchain
|
|
||||||
|
|
||||||
# Build all versions of the firmware in the "builds" folder
|
|
||||||
make docker-build-all
|
|
||||||
```
|
|
||||||
|
|
||||||
The `builds` folder will contain all the variation on the firmware in `.hex` files.
|
|
||||||
|
|
||||||
## Build locally
|
|
||||||
|
|
||||||
If you have the toolchain installed on your machine you can build the firmware with:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd targets/stm32l432
|
cd targets/stm32l432
|
||||||
make cbor
|
make cbor
|
||||||
make build-hacker
|
make build-hacker
|
||||||
@ -95,6 +53,19 @@ solo program aux enter-bootloader
|
|||||||
solo program bootloader targets/stm32l432/solo.hex
|
solo program bootloader targets/stm32l432/solo.hex
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Alternatively, run `make docker-build` and use the firmware generated in `/tmp`.
|
||||||
|
|
||||||
|
If you forgot the `--recurse-submodules` when cloning, simply `git submodule update --init --recursive`.
|
||||||
|
|
||||||
|
For example, if you want to turn off any blue light emission, you can edit [`led_rgb()`](https://github.com/solokeys/solo/blob/master/targets/stm32l432/src/app.h#L48) and change `LED_INIT_VALUE`
|
||||||
|
to be a different hex color.
|
||||||
|
|
||||||
|
Then recompile, load your new firmware, and enjoy a different LED color Solo.
|
||||||
|
|
||||||
|
In the Hacker version, hardware is the same but the firmware is unlocked, so you can 1) load an unsigned application, or 2) entirely reflash the key. By contrast, in a regular Solo you can only upgrade to a firmware signed by SoloKeys, and flash is locked and debug disabled permanently.
|
||||||
|
|
||||||
|
Hacker Solo isn't really secure so you should only use it for development. An attacker with physical access to a Solo for Hacker can reflash it following the steps above, and even a malware on your computer could possibly reflash it.
|
||||||
|
|
||||||
# Developing Solo (No Hardware Needed)
|
# Developing Solo (No Hardware Needed)
|
||||||
|
|
||||||
Clone Solo and build it
|
Clone Solo and build it
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
# Using Solo for passwordless or second factor login on Linux
|
|
||||||
|
|
||||||
## Setup on Ubuntu 18.04
|
|
||||||
Before you can use Solo for passwordless or second factor login in your Linux system you have to install some packages.
|
|
||||||
|
|
||||||
This was tested under **Linux Mint 19.2**.
|
|
||||||
|
|
||||||
First you have to install PAM modules for u2f.
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo apt install libpam-u2f pamu2fcfg
|
|
||||||
```
|
|
||||||
|
|
||||||
## Setting up key
|
|
||||||
To use Solo as passwordless or second factor login, you have to setup your system with your Solo.
|
|
||||||
First create a new folder named **Yubico** in your **.config** folder in your **home** directory
|
|
||||||
|
|
||||||
```
|
|
||||||
mkdir ~/.config/Yubico
|
|
||||||
```
|
|
||||||
|
|
||||||
Then create a new key for PAM U2F module. If it is your first key you want to register use following command:
|
|
||||||
```
|
|
||||||
pamu2fcfg > ~/.config/Yubico/u2f_keys
|
|
||||||
```
|
|
||||||
If you want to register an additional key use this command instead:
|
|
||||||
```
|
|
||||||
pamu2fcfg >> ~/.config/Yubico/u2f_keys
|
|
||||||
```
|
|
||||||
Now press the button on your Solo.
|
|
||||||
|
|
||||||
|
|
||||||
If you can't generate your key (error message), you may add Yubico Team from PPA and install latest libpam-u2f and pamu2fcfg and try again.
|
|
||||||
```
|
|
||||||
sudo add-apt-repository ppa:yubico/stable
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get upgrade
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Login into Linux
|
|
||||||
### Passwordless
|
|
||||||
To login passwordless into your Linux system, you have to edit the file **lightdm** (or **gdm** or which display manager you prefered).
|
|
||||||
In case of lightdm:
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo vim /etc/pam.d/lightdm
|
|
||||||
```
|
|
||||||
Now search following entry:
|
|
||||||
```
|
|
||||||
@include common-auth
|
|
||||||
```
|
|
||||||
and add
|
|
||||||
```
|
|
||||||
auth sufficient pam_u2f.so
|
|
||||||
```
|
|
||||||
**before** @include common-auth.
|
|
||||||
|
|
||||||
Save the file and test it.<br>
|
|
||||||
Insert Solo in your USB port and logout.
|
|
||||||
Now you should be able to login into Linux without password, only with pressing your button on Solo and press enter.
|
|
||||||
|
|
||||||
Why **sufficient**? The difference between the keyword sufficient and required is, if you don't have your Solo available, you can also login, because the system falls back to password mode.
|
|
||||||
|
|
||||||
|
|
||||||
The login mechanism can be also used for additional features like:
|
|
||||||
|
|
||||||
: - Login after screen timeout - edit /etc/pam.d/mate-screensaver (or kde-screensaver, ...)
|
|
||||||
- Passwordless sudo - edit /etc/pam.d/sudo
|
|
||||||
|
|
||||||
Check out your folder **/etc/pam.d/** and do some experiments.
|
|
||||||
|
|
||||||
**But remember:** <br>
|
|
||||||
The login passwordless won't make your system more secure, but maybe more comfortable. If somebody have access to your Solo, this person will be also able to login into your system.
|
|
||||||
|
|
||||||
|
|
||||||
### Solo as second factor
|
|
||||||
To use Solo as second factor, for login into your Linux system, is nearly the same.
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo vim /etc/pam.d/lightdm
|
|
||||||
```
|
|
||||||
Now search following entry:
|
|
||||||
```
|
|
||||||
@include common-auth
|
|
||||||
```
|
|
||||||
and add
|
|
||||||
```
|
|
||||||
auth required pam_u2f.so
|
|
||||||
```
|
|
||||||
**after** @include common-auth.
|
|
||||||
|
|
||||||
Save the file and test it. <br>
|
|
||||||
In case your Solo is not present, your password will be incrorrect. If Solo is plugged into your USB port, it will signal pressing the button and you will be able to login into Linux.
|
|
||||||
|
|
||||||
Why **required**? If you choose the option **sufficent** your Solo is optional. You could also login without second factor if your Solo is not connected.
|
|
||||||
|
|
||||||
**But remember:**<br>
|
|
||||||
If you loose your Solo you won't be able to login into your system.
|
|
@ -1,17 +1,16 @@
|
|||||||
# Booting into bootloader mode
|
# Booting into bootloader mode
|
||||||
|
|
||||||
If you have a recent version of Solo, you can put it into bootloader mode by running this command.
|
You can put Solo into bootloader mode by holding down the button, and plugging in Solo. After 2 seconds, bootloader mode will activate.
|
||||||
|
You'll see a yellowish flashing light and you can let go of the button.
|
||||||
|
|
||||||
|
Now Solo is ready to [accept firmware updates](/solo/signed-updates). If the Solo is a secured model, it can only accept signed updates, typically in the `firmware-*.json` format.
|
||||||
|
|
||||||
|
If Solo is running a hacker build, it can be put into bootloader mode on command. This makes it easier for development.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
solo program aux enter-bootloader
|
solo program aux enter-bootloader
|
||||||
```
|
```
|
||||||
|
|
||||||
If your Solo is a bit older (<=2.5.3) You can put Solo into bootloader mode by using the button method:
|
|
||||||
Hold down button while plugging in Solo. After 2 seconds, bootloader mode will activate.
|
|
||||||
You'll see a yellowish flashing light and you can let go of the button.
|
|
||||||
|
|
||||||
Now Solo is ready to [accept firmware updates](/solo/signed-updates). If the Solo is a secured model, it can only accept signed updates, typically in the `firmware-*.json` format.
|
|
||||||
|
|
||||||
# The boot stages of Solo
|
# The boot stages of Solo
|
||||||
|
|
||||||
Solo has 3 boot stages.
|
Solo has 3 boot stages.
|
||||||
@ -22,8 +21,7 @@ The first stage is the DFU (Device Firmware Update) which is in a ROM on Solo.
|
|||||||
This is what allows the entire firmware of Solo to be programmed. **It's not recommended to develop for Solo using the DFU because
|
This is what allows the entire firmware of Solo to be programmed. **It's not recommended to develop for Solo using the DFU because
|
||||||
if you program broken firmware, you could brick your device**.
|
if you program broken firmware, you could brick your device**.
|
||||||
|
|
||||||
On hacker/nonverifying-bootloader devices, you can boot into the DFU by holding down the button for 5 seconds,
|
On hacker devices, you can boot into the DFU by holding down the button for 5 seconds, when Solo is already in bootloader mode.
|
||||||
when Solo is already in bootloader mode.
|
|
||||||
|
|
||||||
You can also run this command when Solo is in bootloader mode to put it in DFU mode.
|
You can also run this command when Solo is in bootloader mode to put it in DFU mode.
|
||||||
|
|
||||||
@ -31,7 +29,7 @@ You can also run this command when Solo is in bootloader mode to put it in DFU m
|
|||||||
solo program aux enter-dfu
|
solo program aux enter-dfu
|
||||||
```
|
```
|
||||||
|
|
||||||
Note it will stay in DFU mode until you to tell it to boot again. You can boot it again by running the following.
|
Note it will stay in DFU mode until to tell it to boot again. You can boot it again by running the following.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
solo program aux leave-dfu
|
solo program aux leave-dfu
|
||||||
|
@ -36,21 +36,17 @@ Enter the `stm32l4xx` target directory.
|
|||||||
cd targets/stm32l432
|
cd targets/stm32l432
|
||||||
```
|
```
|
||||||
|
|
||||||
Now build the Solo application.
|
Now build Solo.
|
||||||
|
|
||||||
```
|
```
|
||||||
make firmware
|
make build-hacker
|
||||||
```
|
```
|
||||||
|
|
||||||
The `firmware` recipe builds the solo application, and outputs `solo.hex`. You can use this
|
The `build-hacker` recipe does a few things. First it builds the bootloader, with
|
||||||
to reprogram any unlocked/hacker Solo model. Note that it does not include the Solo bootloader,
|
|
||||||
so it is not a full reprogram.
|
|
||||||
|
|
||||||
<!-- First it builds the bootloader, with
|
|
||||||
signature checking disabled. Then it builds the Solo application with "hacker" features
|
signature checking disabled. Then it builds the Solo application with "hacker" features
|
||||||
enabled, like being able to jump to the bootloader on command. It then merges bootloader
|
enabled, like being able to jump to the bootloader on command. It then merges bootloader
|
||||||
and solo builds into the same binary. I.e. it combines `bootloader.hex` and `solo.hex`
|
and solo builds into the same binary. I.e. it combines `bootloader.hex` and `solo.hex`
|
||||||
into `all.hex`. -->
|
into `all.hex`.
|
||||||
|
|
||||||
If you're just planning to do development, **please don't try to reprogram the bootloader**,
|
If you're just planning to do development, **please don't try to reprogram the bootloader**,
|
||||||
as this can be risky if done often. Just use `solo.hex`.
|
as this can be risky if done often. Just use `solo.hex`.
|
||||||
@ -61,13 +57,13 @@ If you're developing, you probably want to see debug messages! Solo has a USB
|
|||||||
Serial port that it will send debug messages through (from `printf`). You can read them using
|
Serial port that it will send debug messages through (from `printf`). You can read them using
|
||||||
a normal serial terminal like `picocom` or `putty`.
|
a normal serial terminal like `picocom` or `putty`.
|
||||||
|
|
||||||
Just add `-debug-1` or `-debug-2` to your build recipe, like this.
|
Just add `DEBUG=1` or `DEBUG=2` to your build recipe, like this.
|
||||||
|
|
||||||
```
|
```
|
||||||
make firmware-debug-1
|
make build-hacker DEBUG=1
|
||||||
```
|
```
|
||||||
|
|
||||||
If you use `debug-2`, that means Solo will not boot until something starts reading
|
If you use `DEBUG=2`, that means Solo will not boot until something starts reading
|
||||||
its debug messages. So it basically waits to tether to a serial terminal so that you don't
|
its debug messages. So it basically waits to tether to a serial terminal so that you don't
|
||||||
miss any debug messages.
|
miss any debug messages.
|
||||||
|
|
||||||
@ -82,45 +78,27 @@ solo monitor <serial-port>
|
|||||||
|
|
||||||
[See issue 62](https://github.com/solokeys/solo/issues/62).
|
[See issue 62](https://github.com/solokeys/solo/issues/62).
|
||||||
|
|
||||||
### Building a complete Solo build (application + bootloader + certificate)
|
### Building a Solo release
|
||||||
|
|
||||||
To make a complete Solo build, you need to build the bootloader. We provide
|
To build Solo
|
||||||
two easy recipes:
|
|
||||||
|
|
||||||
* `bootloader-nonverifying`: bootloader with no signature checking on updates. I.e. "unlocked".
|
If you want to build a release of Solo, we recommend trying a Hacker build first
|
||||||
* `bootloader-verifying`: bootloader with signature checking enforced on updated. I.e. "Locked".
|
just to make sure that it's working. Otherwise it may not be as easy or possible to
|
||||||
|
fix any mistakes.
|
||||||
|
|
||||||
To be safe, let's use the `-nonverifying` build.
|
If you're ready to program a full release, run this recipe to build.
|
||||||
|
|
||||||
```
|
```
|
||||||
make bootloader-nonverifying
|
make build-release-locked
|
||||||
```
|
```
|
||||||
|
|
||||||
This outputs `bootloader.hex`. We can then merge the bootloader and application.
|
This outputs bootloader.hex, solo.hex, and the combined all.hex.
|
||||||
|
|
||||||
```
|
Programming `all.hex` will cause the device to permanently lock itself. This means debuggers cannot be used and signature checking
|
||||||
solo mergehex bootloader.hex solo.hex bundle.hex
|
will be enforced on all future updates.
|
||||||
```
|
|
||||||
|
|
||||||
`bundle.hex` is our complete firmware build. Note it is in this step that you can
|
Note if you program a secured `solo.hex` file onto a Solo Hacker, it will lock the flash, but the bootloader
|
||||||
include a custom attestation certificate or lock the device from debugging/DFU.
|
will still accept unsigned firmware updates. So you can switch it back to being a hacker, but you will
|
||||||
By default the "hacker" attestation certifcate and key is used.
|
not be able to replace the unlocked bootloader anymore, since the permanently locked flash also disables the DFU.
|
||||||
|
[Read more on Solo's boot stages](/solo/bootloader-mode).
|
||||||
```
|
|
||||||
solo mergehex \
|
|
||||||
--attestation-key "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" \
|
|
||||||
--attestation-cert attestation.der \
|
|
||||||
--lock \
|
|
||||||
solo.hex \
|
|
||||||
bootloader.hex \
|
|
||||||
bundle.hex
|
|
||||||
```
|
|
||||||
|
|
||||||
See [here for more information on custom attestation](/solo/customization/).
|
|
||||||
|
|
||||||
If you use `--lock`, this will permanently lock the device to this new bootloader. You
|
|
||||||
won't be able to program the bootloader again or be able to connect a hardware debugger.
|
|
||||||
The new bootloader may be able to accept (signed) updates still, depending on how you configured it.
|
|
||||||
|
|
||||||
To learn more about normal updates or a "full" update, you should [read more on Solo's boot stages](/solo/bootloader-mode).
|
|
||||||
|
|
||||||
|
@ -114,27 +114,28 @@ If the checks succeed, you are ready to program the device attestation key and c
|
|||||||
|
|
||||||
### Programming an attestation key and certificate
|
### Programming an attestation key and certificate
|
||||||
|
|
||||||
First, [Build your solo application and bootloader](/solo/building).
|
Convert the DER format of the device attestation certificate to "C" bytes using our utility script. You may first need to
|
||||||
|
first install prerequisite python modules (`pip install -r tools/requirements.txt`).
|
||||||
|
|
||||||
Print your attestation key in a hex string format. Using our utility script:
|
```
|
||||||
|
python tools/gencert/cbytes.py device_cert.der
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the byte string portion into the [`attestation.c` source file of Solo](https://github.com/solokeys/solo/blob/master/targets/stm32l432/src/attestation.c). Overwrite the development or "default" certificate that is already there.
|
||||||
|
|
||||||
|
Now [build the Solo firmware](/solo/building), either a secure or hacker build. You will need to produce a `bootloader.hex` file and a `solo.hex` file.
|
||||||
|
|
||||||
|
Print your attestation key in a hex string format.
|
||||||
|
|
||||||
```
|
```
|
||||||
python tools/print_x_y.py device_key.pem
|
python tools/print_x_y.py device_key.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
Merge the `bootloader.hex`, `solo.hex`, attestion key, and certificate into one firmware file.
|
Merge the `bootloader.hex`, `solo.hex`, and attestion key into one firmware file.
|
||||||
|
|
||||||
```
|
```
|
||||||
solo mergehex \
|
solo mergehex --attestation-key <attestation-key-hex-string> bootloader.hex solo.hex all.hex
|
||||||
--attestation-key "(The 32-byte hex string extracted from device_key.pem)" \
|
|
||||||
--attestation-cert device_cert.der \
|
|
||||||
--lock \
|
|
||||||
solo.hex \
|
|
||||||
bootloader.hex \
|
|
||||||
bundle.hex
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you have a newly created `bundle.hex` file with a custom attestation key and cert. You can [program this `bundle.hex` file
|
Now you have a newly create `all.hex` file with a custom attestation key. You can [program this `all.hex` file
|
||||||
with Solo in DFU mode](/solo/programming#procedure).
|
with Solo in DFU mode](/solo/programming#procedure).
|
||||||
|
|
||||||
Are you interested in customizing in bulk? Contact hello@solokeys.com and we can help.
|
|
||||||
|
@ -22,11 +22,12 @@ solo key update <--secure | --hacker>
|
|||||||
You can manually install the [latest release](https://github.com/solokeys/solo/releases), or use a build that you made.
|
You can manually install the [latest release](https://github.com/solokeys/solo/releases), or use a build that you made.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# If it's a hacker, it will automatically boot into bootloader mode.
|
||||||
solo program bootloader <firmware.hex | firmware.json>
|
solo program bootloader <firmware.hex | firmware.json>
|
||||||
```
|
```
|
||||||
|
|
||||||
Note you won't be able to use `all.hex` or the `bundle-*.hex` builds, as these include the solo bootloader. You shouldn't
|
Note you won't be able to use `all.hex` or the `bundle-*.hex` builds, as these include the solo bootloader. You shouldn't
|
||||||
risk changing the Solo bootloader unless you want to make it a secure device, or [make other customizations](/solo/customization/).
|
risk changing the Solo bootloader unless you want to make it a secure device, or [make other customizations]().
|
||||||
|
|
||||||
## Updating a Hacker to a Secure Solo
|
## Updating a Hacker to a Secure Solo
|
||||||
|
|
||||||
@ -37,14 +38,14 @@ You can use a firmware build from the [latest release](https://github.com/soloke
|
|||||||
a build that you made yourself.
|
a build that you made yourself.
|
||||||
|
|
||||||
You need to use a firmware file that has the combined bootloader and application (or at the very least just the bootloader).
|
You need to use a firmware file that has the combined bootloader and application (or at the very least just the bootloader).
|
||||||
This means using the `bundle-*.hex` file or the `bundle.hex` from your build. If you overwrite the Solo flash with a missing bootloader,
|
This means using the `bundle-*.hex` file or the `all.hex` from your build. If you overwrite the Solo flash with a missing bootloader,
|
||||||
it will be bricked.
|
it will be bricked.
|
||||||
|
|
||||||
We provide two types of bundled builds. The `bundle-hacker-*.hex` build is the hacker build. If you update with this,
|
We provide two types of bundled builds. The `bundle-hacker-*.hex` build is the hacker build. If you update with this,
|
||||||
you will update the bootloader and application, but nothing will be secured. The `bundle-secure-non-solokeys.hex`
|
you will update the bootloader and application, but nothing will be secured. The `bundle-secure-non-solokeys.hex`
|
||||||
is a secured build that will lock your device and it will behave just like a Secure Solo. The main difference is that
|
is a secured build that will lock your device and it will behave just like a Secure Solo. The main difference is that
|
||||||
it uses a "default" attestation key in the device, rather than the SoloKeys attestation key. There is no security
|
it uses a "default" attestation key in the device, rather than the SoloKeys attestation key. There is no security
|
||||||
concern with using our default attestation key, aside from a small privacy implication that services can distinguish it from Solo Secure.
|
concern with using our default attestation key, aside from a privacy implication that services can distinguish it from Solo Secure.
|
||||||
|
|
||||||
### Procedure
|
### Procedure
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ concern with using our default attestation key, aside from a small privacy impli
|
|||||||
|
|
||||||
2. Program the device
|
2. Program the device
|
||||||
|
|
||||||
solo program dfu <bundle-secure-non-solokeys.hex | bundle.hex>
|
solo program dfu <bundle-secure-non-solokeys.hex | all.hex>
|
||||||
|
|
||||||
Double check you programmed it with bootloader + application (or just bootloader).
|
Double check you programmed it with bootloader + application (or just bootloader).
|
||||||
If you messed it up, simply don't do the next step and repeat this step correctly.
|
If you messed it up, simply don't do the next step and repeat this step correctly.
|
||||||
|
@ -47,7 +47,7 @@ typedef enum
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
const uint8_t * attestation_cert_der;
|
const uint8_t attestation_cert_der[];
|
||||||
const uint16_t attestation_cert_der_size;
|
const uint16_t attestation_cert_der_size;
|
||||||
const uint8_t attestation_key[];
|
const uint8_t attestation_key[];
|
||||||
const uint16_t attestation_key_size;
|
const uint16_t attestation_key_size;
|
||||||
@ -338,7 +338,7 @@ void crypto_aes256_encrypt(uint8_t * buf, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const uint8_t _attestation_cert_der[] =
|
const uint8_t attestation_cert_der[] =
|
||||||
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"
|
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"
|
||||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
|
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
|
||||||
"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e"
|
"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e"
|
||||||
@ -365,11 +365,9 @@ const uint8_t _attestation_cert_der[] =
|
|||||||
"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd"
|
"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd"
|
||||||
"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7"
|
"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7"
|
||||||
"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7";
|
"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7";
|
||||||
const uint8_t * attestation_cert_der = (const uint8_t *)_attestation_cert_der;
|
|
||||||
|
|
||||||
uint16_t attestation_cert_der_get_size(){
|
|
||||||
return sizeof(_attestation_cert_der)-1;
|
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30";
|
const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30";
|
||||||
|
@ -54,7 +54,10 @@ void crypto_reset_master_secret();
|
|||||||
void crypto_load_master_secret(uint8_t * key);
|
void crypto_load_master_secret(uint8_t * key);
|
||||||
|
|
||||||
|
|
||||||
extern const uint8_t * attestation_cert_der;
|
extern const uint8_t attestation_cert_der[];
|
||||||
uint16_t attestation_cert_der_get_size();
|
extern const uint16_t attestation_cert_der_size;
|
||||||
|
|
||||||
|
extern const uint8_t attestation_key[];
|
||||||
|
extern const uint16_t attestation_key_size;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -661,7 +661,7 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
|
|||||||
ret = cbor_encoder_create_array(&stmtmap, &x5carr, 1);
|
ret = cbor_encoder_create_array(&stmtmap, &x5carr, 1);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
{
|
{
|
||||||
ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_get_size());
|
ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_size);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
ret = cbor_encoder_close_container(&stmtmap, &x5carr);
|
ret = cbor_encoder_close_container(&stmtmap, &x5carr);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
|
@ -696,7 +696,7 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
|||||||
{
|
{
|
||||||
ctap_response_init(ctap_resp);
|
ctap_response_init(ctap_resp);
|
||||||
|
|
||||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL))
|
||||||
uint32_t param;
|
uint32_t param;
|
||||||
#endif
|
#endif
|
||||||
#if defined(IS_BOOTLOADER)
|
#if defined(IS_BOOTLOADER)
|
||||||
@ -710,20 +710,23 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
|||||||
printf1(TAG_HID,"CTAPHID_BOOT\n");
|
printf1(TAG_HID,"CTAPHID_BOOT\n");
|
||||||
u2f_set_writeback_buffer(ctap_resp);
|
u2f_set_writeback_buffer(ctap_resp);
|
||||||
is_busy = bootloader_bridge(len, ctap_buffer);
|
is_busy = bootloader_bridge(len, ctap_buffer);
|
||||||
wb->bcnt = 1 + ctap_resp->length;
|
|
||||||
|
|
||||||
ctaphid_write(wb, &is_busy, 1);
|
ctaphid_write(wb, &is_busy, 1);
|
||||||
ctaphid_write(wb, ctap_resp->data, ctap_resp->length);
|
ctaphid_write(wb, ctap_resp->data, ctap_resp->length);
|
||||||
ctaphid_write(wb, NULL, 0);
|
ctaphid_write(wb, NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SOLO)
|
#if defined(SOLO_HACKER)
|
||||||
case CTAPHID_ENTERBOOT:
|
case CTAPHID_ENTERBOOT:
|
||||||
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||||
boot_solo_bootloader();
|
boot_solo_bootloader();
|
||||||
wb->bcnt = 0;
|
wb->bcnt = 0;
|
||||||
ctaphid_write(wb, NULL, 0);
|
ctaphid_write(wb, NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
|
case CTAPHID_ENTERSTBOOT:
|
||||||
|
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||||
|
boot_st_bootloader();
|
||||||
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(IS_BOOTLOADER)
|
#if !defined(IS_BOOTLOADER)
|
||||||
@ -742,21 +745,16 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
|||||||
|
|
||||||
case CTAPHID_GETVERSION:
|
case CTAPHID_GETVERSION:
|
||||||
printf1(TAG_HID,"CTAPHID_GETVERSION\n");
|
printf1(TAG_HID,"CTAPHID_GETVERSION\n");
|
||||||
wb->bcnt = 4;
|
wb->bcnt = 3;
|
||||||
ctap_buffer[0] = SOLO_VERSION_MAJ;
|
ctap_buffer[0] = SOLO_VERSION_MAJ;
|
||||||
ctap_buffer[1] = SOLO_VERSION_MIN;
|
ctap_buffer[1] = SOLO_VERSION_MIN;
|
||||||
ctap_buffer[2] = SOLO_VERSION_PATCH;
|
ctap_buffer[2] = SOLO_VERSION_PATCH;
|
||||||
#if defined(SOLO)
|
ctaphid_write(wb, ctap_buffer, 3);
|
||||||
ctap_buffer[3] = solo_is_locked();
|
|
||||||
#else
|
|
||||||
ctap_buffer[3] = 0;
|
|
||||||
#endif
|
|
||||||
ctaphid_write(wb, ctap_buffer, 4);
|
|
||||||
ctaphid_write(wb, NULL, 0);
|
ctaphid_write(wb, NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL))
|
||||||
case CTAPHID_LOADKEY:
|
case CTAPHID_LOADKEY:
|
||||||
/**
|
/**
|
||||||
* Load external key. Useful for enabling backups.
|
* Load external key. Useful for enabling backups.
|
||||||
|
@ -306,7 +306,7 @@ static int16_t u2f_register(struct u2f_register_request * req)
|
|||||||
uint8_t * sig = (uint8_t*)req;
|
uint8_t * sig = (uint8_t*)req;
|
||||||
|
|
||||||
|
|
||||||
const uint16_t attest_size = attestation_cert_der_get_size();
|
const uint16_t attest_size = attestation_cert_der_size;
|
||||||
|
|
||||||
if ( ! ctap_user_presence_test(750))
|
if ( ! ctap_user_presence_test(750))
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
#!/bin/bash -xe
|
#!/bin/bash -xe
|
||||||
version=$1
|
|
||||||
|
|
||||||
export PREFIX=/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/
|
version=${1:-master}
|
||||||
|
|
||||||
|
export PREFIX=/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/
|
||||||
|
|
||||||
cd /solo/targets/stm32l432
|
cd /solo/targets/stm32l432
|
||||||
ls
|
git fetch --tags
|
||||||
|
git checkout ${version}
|
||||||
|
git submodule update --init --recursive
|
||||||
|
version=$(git describe)
|
||||||
|
|
||||||
make cbor
|
make cbor
|
||||||
|
|
||||||
@ -12,12 +16,13 @@ out_dir="/builds"
|
|||||||
|
|
||||||
function build() {
|
function build() {
|
||||||
part=${1}
|
part=${1}
|
||||||
output=${2}
|
variant=${2}
|
||||||
what="${part}"
|
output=${3:-${part}}
|
||||||
|
what="${part}-${variant}"
|
||||||
|
|
||||||
make full-clean
|
make full-clean
|
||||||
|
|
||||||
make ${what} VERSION_FULL=${version}
|
make ${what}
|
||||||
|
|
||||||
out_hex="${what}-${version}.hex"
|
out_hex="${what}-${version}.hex"
|
||||||
out_sha2="${what}-${version}.sha2"
|
out_sha2="${what}-${version}.sha2"
|
||||||
@ -27,27 +32,24 @@ function build() {
|
|||||||
cp ${out_hex} ${out_sha2} ${out_dir}
|
cp ${out_hex} ${out_sha2} ${out_dir}
|
||||||
}
|
}
|
||||||
|
|
||||||
build bootloader-nonverifying bootloader
|
build bootloader nonverifying
|
||||||
build bootloader-verifying bootloader
|
build bootloader verifying
|
||||||
build firmware solo
|
build firmware hacker solo
|
||||||
build firmware-debug-1 solo
|
build firmware hacker-debug-1 solo
|
||||||
build firmware-debug-2 solo
|
build firmware hacker-debug-2 solo
|
||||||
build firmware solo
|
build firmware secure solo
|
||||||
|
build firmware secure-non-solokeys solo
|
||||||
|
|
||||||
|
pip install -U pip
|
||||||
|
pip install -U solo-python
|
||||||
cd ${out_dir}
|
cd ${out_dir}
|
||||||
|
|
||||||
bundle="bundle-hacker-${version}"
|
bundle="bundle-hacker-${version}"
|
||||||
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-${version}.hex ${bundle}.hex
|
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-hacker-${version}.hex ${bundle}.hex
|
||||||
sha256sum ${bundle}.hex > ${bundle}.sha2
|
sha256sum ${bundle}.hex > ${bundle}.sha2
|
||||||
|
|
||||||
bundle="bundle-hacker-debug-1-${version}"
|
bundle="bundle-hacker-debug-1-${version}"
|
||||||
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-debug-1-${version}.hex ${bundle}.hex
|
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-hacker-debug-1-${version}.hex ${bundle}.hex
|
||||||
sha256sum ${bundle}.hex > ${bundle}.sha2
|
|
||||||
|
|
||||||
bundle="bundle-hacker-debug-2-${version}"
|
bundle="bundle-hacker-debug-2-${version}"
|
||||||
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-debug-2-${version}.hex ${bundle}.hex
|
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-hacker-debug-2-${version}.hex ${bundle}.hex
|
||||||
sha256sum ${bundle}.hex > ${bundle}.sha2
|
|
||||||
|
|
||||||
bundle="bundle-secure-non-solokeys-${version}"
|
bundle="bundle-secure-non-solokeys-${version}"
|
||||||
/opt/conda/bin/solo mergehex --lock bootloader-verifying-${version}.hex firmware-${version}.hex ${bundle}.hex
|
/opt/conda/bin/solo mergehex bootloader-verifying-${version}.hex firmware-secure-non-solokeys-${version}.hex ${bundle}.hex
|
||||||
sha256sum ${bundle}.hex > ${bundle}.sha2
|
sha256sum ${bundle}.hex > ${bundle}.sha2
|
||||||
|
@ -15,7 +15,6 @@ nav:
|
|||||||
- Bootloader mode: solo/bootloader-mode.md
|
- Bootloader mode: solo/bootloader-mode.md
|
||||||
- Customization: solo/customization.md
|
- Customization: solo/customization.md
|
||||||
- Solo Extras: solo/solo-extras.md
|
- Solo Extras: solo/solo-extras.md
|
||||||
- Application Ideas: solo/application-ideas.md
|
|
||||||
- Running on Nucleo32 board: solo/nucleo32-board.md
|
- Running on Nucleo32 board: solo/nucleo32-board.md
|
||||||
- Signed update process: solo/signed-updates.md
|
- Signed update process: solo/signed-updates.md
|
||||||
- Code documentation: solo/code-overview.md
|
- Code documentation: solo/code-overview.md
|
||||||
|
@ -2,9 +2,8 @@ ifndef DEBUG
|
|||||||
DEBUG=0
|
DEBUG=0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
VERSION_FULL?=$(shell git describe)
|
APPMAKE=build/application.mk
|
||||||
APPMAKE=build/application.mk VERSION_FULL=${VERSION_FULL}
|
BOOTMAKE=build/bootloader.mk
|
||||||
BOOTMAKE=build/bootloader.mk VERSION_FULL=${VERSION_FULL}
|
|
||||||
|
|
||||||
merge_hex=solo mergehex
|
merge_hex=solo mergehex
|
||||||
|
|
||||||
@ -13,14 +12,20 @@ merge_hex=solo mergehex
|
|||||||
|
|
||||||
# The following are the main targets for reproducible builds.
|
# The following are the main targets for reproducible builds.
|
||||||
# TODO: better explanation
|
# TODO: better explanation
|
||||||
firmware:
|
firmware-hacker:
|
||||||
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0
|
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
|
||||||
|
|
||||||
firmware-debug-1:
|
firmware-hacker-debug-1:
|
||||||
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=1
|
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=1 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
|
||||||
|
|
||||||
firmware-debug-2:
|
firmware-hacker-debug-2:
|
||||||
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=2
|
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=2 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
|
||||||
|
|
||||||
|
firmware-secure-non-solokeys:
|
||||||
|
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DFLASH_ROP=2'
|
||||||
|
|
||||||
|
firmware-secure:
|
||||||
|
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DUSE_SOLOKEYS_CERT -DFLASH_ROP=2'
|
||||||
|
|
||||||
bootloader-nonverifying:
|
bootloader-nonverifying:
|
||||||
$(MAKE) -f $(BOOTMAKE) -j8 bootloader.hex PREFIX=$(PREFIX) EXTRA_DEFINES='-DSOLO_HACKER' DEBUG=0
|
$(MAKE) -f $(BOOTMAKE) -j8 bootloader.hex PREFIX=$(PREFIX) EXTRA_DEFINES='-DSOLO_HACKER' DEBUG=0
|
||||||
@ -90,7 +95,7 @@ flashboot: bootloader.hex
|
|||||||
STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst
|
STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst
|
||||||
|
|
||||||
flash-firmware:
|
flash-firmware:
|
||||||
$(SZ) -A solo.elf
|
arm-none-eabi-size -A solo.elf
|
||||||
solo program aux enter-bootloader
|
solo program aux enter-bootloader
|
||||||
solo program bootloader solo.hex
|
solo program bootloader solo.hex
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define _APP_H_
|
#define _APP_H_
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#define DEBUG_UART USART1
|
#define DEBUG_UART USART1
|
||||||
|
|
||||||
#ifndef DEBUG_LEVEL
|
#ifndef DEBUG_LEVEL
|
||||||
@ -20,7 +21,6 @@
|
|||||||
#define BOOT_TO_DFU 0
|
#define BOOT_TO_DFU 0
|
||||||
|
|
||||||
|
|
||||||
#define SOLO 1
|
|
||||||
#define IS_BOOTLOADER 1
|
#define IS_BOOTLOADER 1
|
||||||
|
|
||||||
#define ENABLE_U2F_EXTENSIONS
|
#define ENABLE_U2F_EXTENSIONS
|
||||||
@ -64,9 +64,4 @@ int is_authorized_to_boot();
|
|||||||
int is_bootloader_disabled();
|
int is_bootloader_disabled();
|
||||||
void bootloader_heartbeat();
|
void bootloader_heartbeat();
|
||||||
|
|
||||||
// Return 1 if Solo is secure/locked.
|
|
||||||
int solo_is_locked();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,7 +66,7 @@ all: $(TARGET).elf
|
|||||||
|
|
||||||
%.elf: $(OBJ)
|
%.elf: $(OBJ)
|
||||||
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
||||||
$(SZ) $@
|
arm-none-eabi-size $@
|
||||||
|
|
||||||
%.hex: %.elf
|
%.hex: %.elf
|
||||||
$(CP) -O ihex $^ $(TARGET).hex
|
$(CP) -O ihex $^ $(TARGET).hex
|
||||||
|
@ -13,8 +13,8 @@ USB_LIB := lib/usbd/usbd_cdc.c lib/usbd/usbd_cdc_if.c lib/usbd/usbd_composite.c
|
|||||||
lib/usbd/usbd_ctlreq.c lib/usbd/usbd_desc.c lib/usbd/usbd_hid.c \
|
lib/usbd/usbd_ctlreq.c lib/usbd/usbd_desc.c lib/usbd/usbd_hid.c \
|
||||||
lib/usbd/usbd_ccid.c
|
lib/usbd/usbd_ccid.c
|
||||||
|
|
||||||
VERSION_FULL?=$(shell git describe)
|
VERSION:=$(shell git describe --abbrev=0 )
|
||||||
VERSION:=$(shell python -c 'print("$(VERSION_FULL)".split("-")[0])')
|
VERSION_FULL:=$(shell git describe)
|
||||||
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
|
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
|
||||||
VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
|
VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
|
||||||
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
|
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#define SOLO
|
|
||||||
|
|
||||||
#define DEBUG_UART USART1
|
#define DEBUG_UART USART1
|
||||||
|
|
||||||
#ifndef DEBUG_LEVEL
|
#ifndef DEBUG_LEVEL
|
||||||
@ -48,9 +46,6 @@
|
|||||||
void printing_init();
|
void printing_init();
|
||||||
void hw_init(int lf);
|
void hw_init(int lf);
|
||||||
|
|
||||||
// Return 1 if Solo is secure/locked.
|
|
||||||
int solo_is_locked();
|
|
||||||
|
|
||||||
//#define TEST
|
//#define TEST
|
||||||
//#define TEST_POWER
|
//#define TEST_POWER
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
// copied, modified, or distributed except according to those terms.
|
// copied, modified, or distributed except according to those terms.
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "memory_layout.h"
|
|
||||||
|
|
||||||
|
#ifdef USE_SOLOKEYS_CERT
|
||||||
|
|
||||||
const uint8_t attestation_solo_cert_der[] =
|
const uint8_t attestation_cert_der[] =
|
||||||
"\x30\x82\x02\xe1\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
|
"\x30\x82\x02\xe1\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
|
||||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x80\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
|
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x80\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
|
||||||
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
|
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
|
||||||
@ -49,8 +49,11 @@ const uint8_t attestation_solo_cert_der[] =
|
|||||||
"\xf8\x84\xc3\x78\x35\x93\x63\x81\x2e\xbe\xa6\x12\x32\x6e\x29\x90\xc8\x91\x4b\x71"
|
"\xf8\x84\xc3\x78\x35\x93\x63\x81\x2e\xbe\xa6\x12\x32\x6e\x29\x90\xc8\x91\x4b\x71"
|
||||||
"\x52"
|
"\x52"
|
||||||
;
|
;
|
||||||
|
#else
|
||||||
|
|
||||||
const uint8_t attestation_hacker_cert_der[] =
|
// For testing/development only
|
||||||
|
|
||||||
|
const uint8_t attestation_cert_der[] =
|
||||||
"\x30\x82\x02\xe9\x30\x82\x02\x8e\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
|
"\x30\x82\x02\xe9\x30\x82\x02\x8e\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
|
||||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
|
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
|
||||||
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
|
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
|
||||||
@ -91,16 +94,8 @@ const uint8_t attestation_hacker_cert_der[] =
|
|||||||
"\xf3\x87\x61\x82\xd8\xcd\x48\xfc\x57"
|
"\xf3\x87\x61\x82\xd8\xcd\x48\xfc\x57"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
const uint16_t attestation_solo_cert_der_size = sizeof(attestation_solo_cert_der)-1;
|
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1;
|
||||||
const uint16_t attestation_hacker_cert_der_size = sizeof(attestation_hacker_cert_der)-1;
|
|
||||||
|
|
||||||
// const uint16_t attestation_key_size = 32;
|
|
||||||
const uint8_t * attestation_cert_der = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert;
|
|
||||||
|
|
||||||
#include "log.h"
|
|
||||||
uint16_t attestation_cert_der_get_size(){
|
|
||||||
uint16_t sz = (uint16_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size;
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const uint16_t attestation_key_size = 32;
|
||||||
|
@ -194,10 +194,9 @@ void crypto_ecc256_init(void)
|
|||||||
|
|
||||||
void crypto_ecc256_load_attestation_key(void)
|
void crypto_ecc256_load_attestation_key(void)
|
||||||
{
|
{
|
||||||
// static uint8_t _key [32];
|
static uint8_t _key [32];
|
||||||
flash_attestation_page * page =(flash_attestation_page *)ATTESTATION_PAGE_ADDR;
|
memmove(_key, (uint8_t*)ATTESTATION_KEY_ADDR, 32);
|
||||||
// memmove(_key, (uint8_t *)ATTESTATION_KEY_ADDR, 32);
|
_signing_key = _key;
|
||||||
_signing_key = page->attestation_key;
|
|
||||||
_key_len = 32;
|
_key_len = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +34,6 @@
|
|||||||
#define LOW_FREQUENCY 1
|
#define LOW_FREQUENCY 1
|
||||||
#define HIGH_FREQUENCY 0
|
#define HIGH_FREQUENCY 0
|
||||||
|
|
||||||
#define SOLO_FLAG_LOCKED 0x2
|
|
||||||
|
|
||||||
void wait_for_usb_tether(void);
|
void wait_for_usb_tether(void);
|
||||||
|
|
||||||
|
|
||||||
@ -193,98 +191,6 @@ void device_init_button(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int solo_is_locked(){
|
|
||||||
uint64_t device_settings = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings;
|
|
||||||
uint32_t tag = (uint32_t)(device_settings >> 32ull);
|
|
||||||
return tag == ATTESTATION_CONFIGURED_TAG && (device_settings & SOLO_FLAG_LOCKED) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** device_migrate
|
|
||||||
* Depending on version of device, migrates:
|
|
||||||
* * Moves attestation certificate to data segment.
|
|
||||||
* * Creates locked variable and stores in data segment.
|
|
||||||
*
|
|
||||||
* Once in place, this allows all devices to accept same firmware,
|
|
||||||
* rather than using "hacker" and "secure" builds.
|
|
||||||
*/
|
|
||||||
static void device_migrate(){
|
|
||||||
extern const uint16_t attestation_solo_cert_der_size;
|
|
||||||
extern const uint16_t attestation_hacker_cert_der_size;
|
|
||||||
|
|
||||||
extern uint8_t attestation_solo_cert_der[];
|
|
||||||
extern uint8_t attestation_hacker_cert_der[];
|
|
||||||
|
|
||||||
uint64_t device_settings = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings;
|
|
||||||
uint32_t configure_tag = (uint32_t)(device_settings >> 32);
|
|
||||||
|
|
||||||
if (configure_tag != ATTESTATION_CONFIGURED_TAG)
|
|
||||||
{
|
|
||||||
printf1(TAG_RED,"Migrating certificate and lock information to data segment.\r\n");
|
|
||||||
|
|
||||||
device_settings = ATTESTATION_CONFIGURED_TAG;
|
|
||||||
device_settings <<= 32;
|
|
||||||
|
|
||||||
// Read current device lock level.
|
|
||||||
uint32_t optr = FLASH->OPTR;
|
|
||||||
if ((optr & 0xff) != 0xAA){
|
|
||||||
device_settings |= SOLO_FLAG_LOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t tmp_attestation_key[32];
|
|
||||||
|
|
||||||
memmove(tmp_attestation_key,
|
|
||||||
((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_key,
|
|
||||||
32);
|
|
||||||
|
|
||||||
flash_erase_page(ATTESTATION_PAGE);
|
|
||||||
flash_write(
|
|
||||||
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_key,
|
|
||||||
tmp_attestation_key,
|
|
||||||
32
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check if this is Solo Hacker attestation (not confidential)
|
|
||||||
// then write solo or hacker attestation cert to flash page.
|
|
||||||
uint8_t solo_hacker_attestation_key[32] = "\x1b\x26\x26\xec\xc8\xf6\x9b\x0f\x69\xe3\x4f"
|
|
||||||
"\xb2\x36\xd7\x64\x66\xba\x12\xac\x16\xc3\xab"
|
|
||||||
"\x57\x50\xba\x06\x4e\x8b\x90\xe0\x24\x48";
|
|
||||||
|
|
||||||
if (memcmp(solo_hacker_attestation_key,
|
|
||||||
tmp_attestation_key,
|
|
||||||
32) == 0)
|
|
||||||
{
|
|
||||||
printf1(TAG_GREEN,"Updating solo hacker cert\r\n");
|
|
||||||
flash_write_dword(
|
|
||||||
(uint32_t)&((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size,
|
|
||||||
(uint64_t)attestation_hacker_cert_der_size
|
|
||||||
);
|
|
||||||
flash_write(
|
|
||||||
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert,
|
|
||||||
attestation_hacker_cert_der,
|
|
||||||
attestation_hacker_cert_der_size
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf1(TAG_GREEN,"Updating solo secure cert\r\n");
|
|
||||||
flash_write_dword(
|
|
||||||
(uint32_t)&((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size,
|
|
||||||
(uint64_t)attestation_solo_cert_der_size
|
|
||||||
);
|
|
||||||
flash_write(
|
|
||||||
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert,
|
|
||||||
attestation_solo_cert_der,
|
|
||||||
attestation_solo_cert_der_size
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save / done.
|
|
||||||
flash_write_dword(
|
|
||||||
(uint32_t) & ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings,
|
|
||||||
(uint64_t)device_settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_init(int argc, char *argv[])
|
void device_init(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -313,8 +219,6 @@ void device_init(int argc, char *argv[])
|
|||||||
ctaphid_init();
|
ctaphid_init();
|
||||||
ctap_init();
|
ctap_init();
|
||||||
|
|
||||||
device_migrate();
|
|
||||||
|
|
||||||
#if BOOT_TO_DFU
|
#if BOOT_TO_DFU
|
||||||
flash_option_bytes_init(1);
|
flash_option_bytes_init(1);
|
||||||
#else
|
#else
|
||||||
|
@ -31,18 +31,21 @@ static void flash_unlock(void)
|
|||||||
// Locks flash and turns off DFU
|
// Locks flash and turns off DFU
|
||||||
void flash_option_bytes_init(int boot_from_dfu)
|
void flash_option_bytes_init(int boot_from_dfu)
|
||||||
{
|
{
|
||||||
|
#ifndef FLASH_ROP
|
||||||
|
#define FLASH_ROP 0
|
||||||
|
#endif
|
||||||
|
#if FLASH_ROP == 0
|
||||||
uint32_t val = 0xfffff8aa;
|
uint32_t val = 0xfffff8aa;
|
||||||
|
#elif FLASH_ROP == 2
|
||||||
|
uint32_t val = 0xfffff8cc;
|
||||||
|
#else
|
||||||
|
uint32_t val = 0xfffff8b9;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (boot_from_dfu){
|
if (boot_from_dfu)
|
||||||
|
{
|
||||||
val &= ~(1<<27); // nBOOT0 = 0 (boot from system rom)
|
val &= ~(1<<27); // nBOOT0 = 0 (boot from system rom)
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (solo_is_locked())
|
|
||||||
{
|
|
||||||
val = 0xfffff8cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val &= ~(1<<26); // nSWBOOT0 = 0 (boot from nBoot0)
|
val &= ~(1<<26); // nSWBOOT0 = 0 (boot from nBoot0)
|
||||||
val &= ~(1<<25); // SRAM2_RST = 1 (erase sram on reset)
|
val &= ~(1<<25); // SRAM2_RST = 1 (erase sram on reset)
|
||||||
val &= ~(1<<24); // SRAM2_PE = 1 (parity check en)
|
val &= ~(1<<24); // SRAM2_PE = 1 (parity check en)
|
||||||
|
@ -17,11 +17,8 @@
|
|||||||
#define COUNTER1_PAGE (PAGES - 3)
|
#define COUNTER1_PAGE (PAGES - 3)
|
||||||
|
|
||||||
// State of FIDO2 application
|
// State of FIDO2 application
|
||||||
#define STATE2_PAGE (PAGES - 2)
|
#define STATE2_PAGE (PAGES - 2)
|
||||||
#define STATE1_PAGE (PAGES - 1)
|
#define STATE1_PAGE (PAGES - 1)
|
||||||
|
|
||||||
#define STATE1_PAGE_ADDR (0x08000000 + ((STATE1_PAGE)*PAGE_SIZE))
|
|
||||||
#define STATE2_PAGE_ADDR (0x08000000 + ((STATE2_PAGE)*PAGE_SIZE))
|
|
||||||
|
|
||||||
// Storage of FIDO2 resident keys
|
// Storage of FIDO2 resident keys
|
||||||
#define RK_NUM_PAGES 10
|
#define RK_NUM_PAGES 10
|
||||||
@ -35,8 +32,8 @@
|
|||||||
#define APPLICATION_START_ADDR (0x08000000 + ((APPLICATION_START_PAGE)*PAGE_SIZE))
|
#define APPLICATION_START_ADDR (0x08000000 + ((APPLICATION_START_PAGE)*PAGE_SIZE))
|
||||||
|
|
||||||
// where attestation key is located
|
// where attestation key is located
|
||||||
#define ATTESTATION_PAGE (PAGES - 15)
|
#define ATTESTATION_KEY_PAGE (PAGES - 15)
|
||||||
#define ATTESTATION_PAGE_ADDR (0x08000000 + ATTESTATION_PAGE*PAGE_SIZE)
|
#define ATTESTATION_KEY_ADDR (0x08000000 + ATTESTATION_KEY_PAGE*PAGE_SIZE)
|
||||||
|
|
||||||
// End of application code. Leave some extra room for future data storage.
|
// End of application code. Leave some extra room for future data storage.
|
||||||
// NOT included in application
|
// NOT included in application
|
||||||
@ -51,6 +48,7 @@
|
|||||||
#define BOOT_VERSION_ADDR (0x08000000 + BOOT_VERSION_PAGE*FLASH_PAGE_SIZE + 8)
|
#define BOOT_VERSION_ADDR (0x08000000 + BOOT_VERSION_PAGE*FLASH_PAGE_SIZE + 8)
|
||||||
#define LAST_PAGE (APPLICATION_END_PAGE-1)
|
#define LAST_PAGE (APPLICATION_END_PAGE-1)
|
||||||
|
|
||||||
|
|
||||||
struct flash_memory_st{
|
struct flash_memory_st{
|
||||||
uint8_t bootloader[APPLICATION_START_PAGE*2*1024];
|
uint8_t bootloader[APPLICATION_START_PAGE*2*1024];
|
||||||
uint8_t application[(APPLICATION_END_PAGE-APPLICATION_START_PAGE)*2*1024-8];
|
uint8_t application[(APPLICATION_END_PAGE-APPLICATION_START_PAGE)*2*1024-8];
|
||||||
@ -67,19 +65,5 @@ typedef struct flash_memory_st flash_memory_st;
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
static_assert(sizeof(flash_memory_st) == 256*1024, "Data structure doesn't match flash size");
|
static_assert(sizeof(flash_memory_st) == 256*1024, "Data structure doesn't match flash size");
|
||||||
|
|
||||||
#define ATTESTATION_CONFIGURED_TAG 0xaa551e78
|
|
||||||
|
|
||||||
struct flash_attestation_page{
|
|
||||||
uint8_t attestation_key[32];
|
|
||||||
// DWORD padded.
|
|
||||||
uint64_t device_settings;
|
|
||||||
uint64_t attestation_cert_size;
|
|
||||||
uint8_t attestation_cert[2048 - 32 - 8 - 8];
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
typedef struct flash_attestation_page flash_attestation_page;
|
|
||||||
|
|
||||||
static_assert(sizeof(flash_attestation_page) == 2048, "Data structure doesn't match flash size");
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user