Compare commits
28 Commits
backup_imp
...
aaguid_cer
Author | SHA1 | Date | |
---|---|---|---|
5b2d85bbbf | |||
522a18a687 | |||
4370c9145e | |||
e2c34fd53d | |||
f35d79ad03 | |||
f70c856998 | |||
2170036672 | |||
af23e84a8d | |||
9650d99b34 | |||
145b04750e | |||
078acbc4b4 | |||
670a4e5d62 | |||
de55e521cc | |||
bbfe51499f | |||
6cb15a6482 | |||
85ddc40036 | |||
1d63154699 | |||
ee55bf3ba0 | |||
3b4b6dd4fe | |||
28e607ddac | |||
dcd256faf4 | |||
85365c635d | |||
a388607dab | |||
d266e7927c | |||
0ac074e8a8 | |||
67eb721da2 | |||
6b5d353501 | |||
bacce7d978 |
@ -207,6 +207,17 @@
|
|||||||
"infra",
|
"infra",
|
||||||
"test"
|
"test"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Nitrokey",
|
||||||
|
"name": "Nitrokey",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/9438831?v=4",
|
||||||
|
"profile": "https://www.nitrokey.com",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"test",
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
57
Makefile
57
Makefile
@ -1,3 +1,5 @@
|
|||||||
|
include fido2/version.mk
|
||||||
|
|
||||||
#define uECC_arch_other 0
|
#define uECC_arch_other 0
|
||||||
#define uECC_x86 1
|
#define uECC_x86 1
|
||||||
#define uECC_x86_64 2
|
#define uECC_x86_64 2
|
||||||
@ -6,44 +8,34 @@
|
|||||||
#define uECC_arm_thumb2 5
|
#define uECC_arm_thumb2 5
|
||||||
#define uECC_arm64 6
|
#define uECC_arm64 6
|
||||||
#define uECC_avr 7
|
#define uECC_avr 7
|
||||||
|
|
||||||
ecc_platform=2
|
ecc_platform=2
|
||||||
|
|
||||||
src = $(wildcard pc/*.c) $(wildcard fido2/*.c) $(wildcard fido2/extensions/*.c) \
|
src = pc/device.c pc/main.c
|
||||||
$(wildcard crypto/sha256/*.c) crypto/tiny-AES-c/aes.c
|
|
||||||
|
|
||||||
obj = $(src:.c=.o) crypto/micro-ecc/uECC.o
|
obj = $(src:.c=.o)
|
||||||
|
|
||||||
LIBCBOR = tinycbor/lib/libtinycbor.a
|
LIBCBOR = tinycbor/lib/libtinycbor.a
|
||||||
|
LIBSOLO = fido2/libsolo.a
|
||||||
|
|
||||||
ifeq ($(shell uname -s),Darwin)
|
ifeq ($(shell uname -s),Darwin)
|
||||||
export LDFLAGS = -Wl,-dead_strip
|
export LDFLAGS = -Wl,-dead_strip
|
||||||
else
|
else
|
||||||
export LDFLAGS = -Wl,--gc-sections
|
export LDFLAGS = -Wl,--gc-sections
|
||||||
endif
|
endif
|
||||||
LDFLAGS += $(LIBCBOR)
|
LDFLAGS += $(LIBSOLO) $(LIBCBOR)
|
||||||
|
|
||||||
VERSION_FULL:=$(shell git describe)
|
|
||||||
VERSION:=$(shell python -c 'print("$(VERSION_FULL)".split("-")[0])')
|
|
||||||
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
|
|
||||||
VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
|
|
||||||
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
|
|
||||||
|
|
||||||
VERSION_FLAGS= -DSOLO_VERSION_MAJ=$(VERSION_MAJ) -DSOLO_VERSION_MIN=$(VERSION_MIN) \
|
CFLAGS = -O2 -fdata-sections -ffunction-sections -g
|
||||||
-DSOLO_VERSION_PATCH=$(VERSION_PAT) -DSOLO_VERSION=\"$(VERSION_FULL)\"
|
ECC_CFLAGS = -O2 -fdata-sections -ffunction-sections -DuECC_PLATFORM=$(ecc_platform)
|
||||||
|
|
||||||
CFLAGS = -O2 -fdata-sections -ffunction-sections $(VERSION_FLAGS) -g
|
INCLUDES = -I../ -I./fido2/ -I./pc -I../pc -I./tinycbor/src
|
||||||
|
|
||||||
INCLUDES = -I./tinycbor/src -I./crypto/sha256 -I./crypto/micro-ecc/ -Icrypto/tiny-AES-c/ -I./fido2/ -I./pc -I./fido2/extensions
|
|
||||||
INCLUDES += -I./crypto/cifra/src
|
|
||||||
|
|
||||||
CFLAGS += $(INCLUDES)
|
CFLAGS += $(INCLUDES)
|
||||||
# for crypto/tiny-AES-c
|
CFLAGS += -DAES256=1 -DSOLO_EXPERIMENTAL=1 -DDEBUG_LEVEL=1
|
||||||
CFLAGS += -DAES256=1 -DAPP_CONFIG=\"app.h\" -DSOLO_EXPERIMENTAL=1
|
|
||||||
|
|
||||||
name = main
|
name = main
|
||||||
|
|
||||||
.PHONY: all $(LIBCBOR) black blackcheck cppcheck wink fido2-test clean full-clean travis test clean version
|
.PHONY: all $(LIBCBOR) $(LIBSOLO) black blackcheck cppcheck wink fido2-test clean full-clean travis test clean version
|
||||||
all: main
|
all: main
|
||||||
|
|
||||||
tinycbor/Makefile crypto/tiny-AES-c/aes.c:
|
tinycbor/Makefile crypto/tiny-AES-c/aes.c:
|
||||||
@ -53,7 +45,10 @@ tinycbor/Makefile crypto/tiny-AES-c/aes.c:
|
|||||||
cbor: $(LIBCBOR)
|
cbor: $(LIBCBOR)
|
||||||
|
|
||||||
$(LIBCBOR):
|
$(LIBCBOR):
|
||||||
cd tinycbor/ && $(MAKE) clean && $(MAKE) LDFLAGS='' -j8
|
cd tinycbor/ && $(MAKE) LDFLAGS='' -j8
|
||||||
|
|
||||||
|
$(LIBSOLO):
|
||||||
|
cd fido2/ && $(MAKE) CFLAGS="$(CFLAGS)" ECC_CFLAGS="$(ECC_CFLAGS)" APP_CONFIG=app.h -j8
|
||||||
|
|
||||||
version:
|
version:
|
||||||
@git describe
|
@git describe
|
||||||
@ -62,16 +57,13 @@ 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)" VERSION_FULL=${SOLO_VERSION_FULL}
|
||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
$(MAKE) cppcheck
|
$(MAKE) cppcheck
|
||||||
|
|
||||||
$(name): $(obj) $(LIBCBOR)
|
$(name): $(obj) $(LIBCBOR) $(LIBSOLO)
|
||||||
$(CC) $(LDFLAGS) -o $@ $(obj) $(LDFLAGS)
|
$(CC) $(LDFLAGS) -o $@ $(obj) $(LDFLAGS)
|
||||||
|
|
||||||
crypto/micro-ecc/uECC.o: ./crypto/micro-ecc/uECC.c
|
|
||||||
$(CC) -c -o $@ $^ -O2 -fdata-sections -ffunction-sections -DuECC_PLATFORM=$(ecc_platform) -I./crypto/micro-ecc/
|
|
||||||
|
|
||||||
venv:
|
venv:
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
venv/bin/pip -q install --upgrade pip
|
venv/bin/pip -q install --upgrade pip
|
||||||
@ -98,20 +90,20 @@ DOCKER_TOOLCHAIN_IMAGE := "solokeys/solo-firmware-toolchain"
|
|||||||
|
|
||||||
docker-build-toolchain:
|
docker-build-toolchain:
|
||||||
docker build -t $(DOCKER_TOOLCHAIN_IMAGE) .
|
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):${SOLO_VERSION}
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}
|
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${SOLO_VERSION_MAJ}
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}.${VERSION_MIN}
|
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${SOLO_VERSION_MAJ}.${SOLO_VERSION_MIN}
|
||||||
|
|
||||||
uncached-docker-build-toolchain:
|
uncached-docker-build-toolchain:
|
||||||
docker build --no-cache -t $(DOCKER_TOOLCHAIN_IMAGE) .
|
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):${SOLO_VERSION}
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}
|
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${SOLO_VERSION_MAJ}
|
||||||
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}.${VERSION_MIN}
|
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${SOLO_VERSION_MAJ}.${SOLO_VERSION_MIN}
|
||||||
|
|
||||||
docker-build-all:
|
docker-build-all:
|
||||||
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
||||||
-v "$(CURDIR):/solo" \
|
-v "$(CURDIR):/solo" \
|
||||||
$(DOCKER_TOOLCHAIN_IMAGE) "solo/in-docker-build.sh" ${VERSION_FULL}
|
$(DOCKER_TOOLCHAIN_IMAGE) "solo/in-docker-build.sh" ${SOLO_VERSION_FULL}
|
||||||
|
|
||||||
CPPCHECK_FLAGS=--quiet --error-exitcode=2
|
CPPCHECK_FLAGS=--quiet --error-exitcode=2
|
||||||
|
|
||||||
@ -128,6 +120,7 @@ clean:
|
|||||||
(cd `dirname $$f` ; git checkout -- .) ;\
|
(cd `dirname $$f` ; git checkout -- .) ;\
|
||||||
fi ;\
|
fi ;\
|
||||||
done
|
done
|
||||||
|
cd fido2 && $(MAKE) clean
|
||||||
|
|
||||||
full-clean: clean
|
full-clean: clean
|
||||||
rm -rf venv
|
rm -rf venv
|
||||||
|
@ -168,6 +168,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<td align="center"><a href="https://github.com/jolo1581"><img src="https://avatars1.githubusercontent.com/u/53423977?v=4" width="100px;" alt="Jan A."/><br /><sub><b>Jan A.</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Code">💻</a> <a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/jolo1581"><img src="https://avatars1.githubusercontent.com/u/53423977?v=4" width="100px;" alt="Jan A."/><br /><sub><b>Jan A.</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Code">💻</a> <a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/ccinelli"><img src="https://avatars0.githubusercontent.com/u/38021940?v=4" width="100px;" alt="ccinelli"/><br /><sub><b>ccinelli</b></sub></a><br /><a href="#infra-ccinelli" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/solokeys/solo/commits?author=ccinelli" title="Tests">⚠️</a></td>
|
<td align="center"><a href="https://github.com/ccinelli"><img src="https://avatars0.githubusercontent.com/u/38021940?v=4" width="100px;" alt="ccinelli"/><br /><sub><b>ccinelli</b></sub></a><br /><a href="#infra-ccinelli" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/solokeys/solo/commits?author=ccinelli" title="Tests">⚠️</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://www.nitrokey.com"><img src="https://avatars1.githubusercontent.com/u/9438831?v=4" width="100px;" alt="Nitrokey"/><br /><sub><b>Nitrokey</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=Nitrokey" title="Code">💻</a> <a href="https://github.com/solokeys/solo/commits?author=Nitrokey" title="Tests">⚠️</a> <a href="#ideas-Nitrokey" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
@ -183,7 +186,7 @@ You may use Solo software under the terms of either the Apache 2.0 license or MI
|
|||||||
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
||||||
|
|
||||||
All hardware, unless otherwise noted, is dual licensed under CERN and CC-BY-SA.
|
All hardware, unless otherwise noted, is dual licensed under CERN and CC-BY-SA.
|
||||||
You may use Solo hardware under the terms of either the CERN 2.1 license or CC-BY-SA 4.0 license.
|
You may use Solo hardware under the terms of either the CERN 1.2 license or CC-BY-SA 4.0 license.
|
||||||
|
|
||||||
All documentation, unless otherwise noted, is licensed under CC-BY-SA.
|
All documentation, unless otherwise noted, is licensed under CC-BY-SA.
|
||||||
You may use Solo documentation under the terms of the CC-BY-SA 4.0 license
|
You may use Solo documentation under the terms of the CC-BY-SA 4.0 license
|
||||||
@ -200,7 +203,7 @@ You can buy Solo, Solo Tap, and Solo for Hackers at [solokeys.com](https://solok
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
[](https://github.com/solokeys/solo/blob/master/LICENSE)
|
[](https://github.com/solokeys/solo/blob/master/LICENSE)
|
||||||
[](#contributors)
|
[](#contributors)
|
||||||
[](https://travis-ci.com/solokeys/solo)
|
[](https://travis-ci.com/solokeys/solo)
|
||||||
[](https://discourse.solokeys.com)
|
[](https://discourse.solokeys.com)
|
||||||
[](https://keybase.io/team/solokeys.public)
|
[](https://keybase.io/team/solokeys.public)
|
||||||
|
60
docs/solo/porting.md
Normal file
60
docs/solo/porting.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Usage and Porting
|
||||||
|
|
||||||
|
Solo is designed to be used as a library or ported to other platforms easily. Here is an example
|
||||||
|
`main()` function.
|
||||||
|
|
||||||
|
```c
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
uint8_t hidmsg[64];
|
||||||
|
uint32_t t1 = 0;
|
||||||
|
|
||||||
|
device_init();
|
||||||
|
memset(hidmsg,0,sizeof(hidmsg));
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (usbhid_recv(hidmsg) > 0)
|
||||||
|
{
|
||||||
|
ctaphid_handle_packet(hidmsg); // pass into libsolo!
|
||||||
|
memset(hidmsg, 0, sizeof(hidmsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ctaphid_check_timeouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
`ctaphid_handle_packet(hidmsg);` is the entrance into the HID layer of libsolo, and will buffer packets and pass them
|
||||||
|
into FIDO2 or U2F layers.
|
||||||
|
|
||||||
|
Everything in the library is cross-platform, but it needs some functions implemented that are usually
|
||||||
|
platform specific. For example, how should libsolo implement an atomic counter? Where should it save state?
|
||||||
|
For all of these platform specific functions, the library contains it's own `weak` definition, so the library will compile and run.
|
||||||
|
LibSolo by default will not try to use an atomic
|
||||||
|
counter or save data persistently -- that needs to be implemented externally.
|
||||||
|
|
||||||
|
If you are using libsolo on another platform,
|
||||||
|
you should take a look at these possibly platform specific functions. They are listed in `fido2/device.h`.
|
||||||
|
If you'd like to reimplement any of the functions, then simply implement the function and compile normally.
|
||||||
|
GCC will replace libsolo's `weak` defined functions (everything in `fido2/device.h`) with your functions. By doing this, you
|
||||||
|
are replacing the function that is used by libsolo.
|
||||||
|
|
||||||
|
To get the library to compile
|
||||||
|
and run, you only need to implement one function for libsolo: `usbhid_send(uint8_t * send)`, which
|
||||||
|
is called by the library to send a 64 byte packet over a USB HID endpoint. In essence, you are giving
|
||||||
|
libsolo a function to write to USB.
|
||||||
|
|
||||||
|
The rest of the definitions in `fido2/device.h` are not required to compile and run so you can
|
||||||
|
immediately hit the ground running and iterative add what else you need. You'll definitely want
|
||||||
|
to continue implementing other functions in `fido2/device.h`. For example, no data will be stored
|
||||||
|
persistently until you define how it can be done!
|
||||||
|
|
||||||
|
For examples, check out the build for STM32L4 and PC (check out `pc/device` and `targets/stm32l432/src/device.c`).
|
||||||
|
|
||||||
|
If there's something that doesn't work for you -- send a pull request! It's better if we can
|
||||||
|
work together off of the same repo and not fork.
|
44
fido2/Makefile
Normal file
44
fido2/Makefile
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
include version.mk
|
||||||
|
|
||||||
|
ifndef APP_CONFIG
|
||||||
|
APP_CONFIG=example_app.h
|
||||||
|
endif
|
||||||
|
|
||||||
|
INC = -I./ -I./extensions
|
||||||
|
INC += -I../tinycbor/src
|
||||||
|
INC += -I../crypto/sha256 -I../crypto/micro-ecc -I../crypto/tiny-AES-c
|
||||||
|
INC += -I../crypto/cifra/src -I../crypto/cifra/src/ext
|
||||||
|
|
||||||
|
INT_CFLAGS = -DAPP_CONFIG=\"$(APP_CONFIG)\"
|
||||||
|
INT_CFLAGS += $(INC)
|
||||||
|
INT_CFLAGS += $(SOLO_VERSION_FLAGS)
|
||||||
|
|
||||||
|
SRC = apdu.c util.c u2f.c test_power.c
|
||||||
|
SRC += stubs.c log.c ctaphid.c ctap.c
|
||||||
|
SRC += ctap_parse.c crypto.c
|
||||||
|
SRC += device.c
|
||||||
|
SRC += version.c
|
||||||
|
SRC += data_migration.c
|
||||||
|
SRC += extensions/extensions.c extensions/solo.c
|
||||||
|
SRC += extensions/wallet.c
|
||||||
|
|
||||||
|
# Crypto libs
|
||||||
|
SRC += ../crypto/sha256/sha256.c ../crypto/micro-ecc/uECC.c ../crypto/tiny-AES-c/aes.c
|
||||||
|
SRC += ../crypto/cifra/src/sha512.c ../crypto/cifra/src/blockwise.c
|
||||||
|
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
all: libsolo.a
|
||||||
|
|
||||||
|
libsolo.a: $(OBJ)
|
||||||
|
$(AR) cqs $@ $^
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $^ $(INT_CFLAGS) $(CFLAGS) -c -o $@
|
||||||
|
|
||||||
|
../crypto/micro-ecc/uECC.o: ../crypto/micro-ecc/uECC.c
|
||||||
|
$(CC) $^ $(INT_CFLAGS) $(ECC_CFLAGS) -c -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) libsolo.a
|
||||||
|
|
145
fido2/crypto.c
145
fido2/crypto.c
@ -5,29 +5,33 @@
|
|||||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||||
// copied, modified, or distributed except according to those terms.
|
// copied, modified, or distributed except according to those terms.
|
||||||
/*
|
/*
|
||||||
* Wrapper for crypto implementation on device
|
* Wrapper for crypto implementation on device.
|
||||||
|
*
|
||||||
|
* Can be replaced with different crypto implementation by
|
||||||
|
* defining EXTERNAL_SOLO_CRYPTO
|
||||||
*
|
*
|
||||||
* */
|
* */
|
||||||
|
#ifndef EXTERNAL_SOLO_CRYPTO
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
|
||||||
#ifdef USE_SOFTWARE_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
#include "uECC.h"
|
#include "uECC.h"
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "ctap.h"
|
#include "ctap.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "log.h"
|
// stuff for SHA512
|
||||||
|
#include "sha2.h"
|
||||||
|
#include "blockwise.h"
|
||||||
#include APP_CONFIG
|
#include APP_CONFIG
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef USING_PC
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
MBEDTLS_ECP_DP_NONE = 0,
|
MBEDTLS_ECP_DP_NONE = 0,
|
||||||
@ -44,53 +48,56 @@ typedef enum
|
|||||||
MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
|
MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
|
||||||
MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
|
MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
|
||||||
} mbedtls_ecp_group_id;
|
} mbedtls_ecp_group_id;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
const uint8_t * attestation_cert_der;
|
|
||||||
const uint16_t attestation_cert_der_size;
|
|
||||||
const uint8_t attestation_key[];
|
|
||||||
const uint16_t attestation_key_size;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static SHA256_CTX sha256_ctx;
|
static SHA256_CTX sha256_ctx;
|
||||||
|
static cf_sha512_context sha512_ctx;
|
||||||
static const struct uECC_Curve_t * _es256_curve = NULL;
|
static const struct uECC_Curve_t * _es256_curve = NULL;
|
||||||
static const uint8_t * _signing_key = NULL;
|
static const uint8_t * _signing_key = NULL;
|
||||||
static int _key_len = 0;
|
static int _key_len = 0;
|
||||||
|
|
||||||
// Secrets for testing only
|
// Secrets for testing only
|
||||||
static uint8_t master_secret[64];
|
static uint8_t master_secret[64];
|
||||||
|
|
||||||
static uint8_t transport_secret[32];
|
static uint8_t transport_secret[32];
|
||||||
|
|
||||||
|
|
||||||
|
void crypto_sha256_init(void)
|
||||||
void crypto_sha256_init()
|
|
||||||
{
|
{
|
||||||
sha256_init(&sha256_ctx);
|
sha256_init(&sha256_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_reset_master_secret()
|
void crypto_sha512_init(void)
|
||||||
{
|
{
|
||||||
ctap_generate_rng(master_secret, 64);
|
cf_sha512_init(&sha512_ctx);
|
||||||
ctap_generate_rng(transport_secret, 32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_load_master_secret(uint8_t * key)
|
void crypto_load_master_secret(uint8_t * key)
|
||||||
{
|
{
|
||||||
#if KEY_SPACE_BYTES < 96
|
#if KEY_SPACE_BYTES < 96
|
||||||
#error "need more key bytes"
|
#error "need more key bytes"
|
||||||
#endif
|
#endif
|
||||||
memmove(master_secret, key, 64);
|
memmove(master_secret, key, 64);
|
||||||
memmove(transport_secret, key+64, 32);
|
memmove(transport_secret, key+64, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void crypto_reset_master_secret(void)
|
||||||
|
{
|
||||||
|
memset(master_secret, 0, 64);
|
||||||
|
memset(transport_secret, 0, 32);
|
||||||
|
ctap_generate_rng(master_secret, 64);
|
||||||
|
ctap_generate_rng(transport_secret, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void crypto_sha256_update(uint8_t * data, size_t len)
|
void crypto_sha256_update(uint8_t * data, size_t len)
|
||||||
{
|
{
|
||||||
sha256_update(&sha256_ctx, data, len);
|
sha256_update(&sha256_ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_update(const uint8_t * data, size_t len) {
|
||||||
|
cf_sha512_update(&sha512_ctx, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
void crypto_sha256_update_secret()
|
void crypto_sha256_update_secret()
|
||||||
{
|
{
|
||||||
sha256_update(&sha256_ctx, master_secret, 32);
|
sha256_update(&sha256_ctx, master_secret, 32);
|
||||||
@ -101,26 +108,32 @@ void crypto_sha256_final(uint8_t * hash)
|
|||||||
sha256_final(&sha256_ctx, hash);
|
sha256_final(&sha256_ctx, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_final(uint8_t * hash)
|
||||||
|
{
|
||||||
|
// NB: there is also cf_sha512_digest
|
||||||
|
cf_sha512_digest_final(&sha512_ctx, hash);
|
||||||
|
}
|
||||||
|
|
||||||
void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
||||||
{
|
{
|
||||||
uint8_t buf[64];
|
uint8_t buf[64];
|
||||||
int i;
|
unsigned int i;
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
if (key == CRYPTO_MASTER_KEY)
|
if (key == CRYPTO_MASTER_KEY)
|
||||||
{
|
{
|
||||||
key = master_secret;
|
key = master_secret;
|
||||||
klen = sizeof(master_secret);
|
klen = sizeof(master_secret)/2;
|
||||||
}
|
}
|
||||||
else if (key == CRYPTO_TRANSPORT_KEY)
|
else if (key == CRYPTO_TRANSPORT_KEY)
|
||||||
{
|
{
|
||||||
key = transport_secret;
|
key = transport_secret;
|
||||||
klen = 32;
|
klen = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(klen > 64)
|
if(klen > 64)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"Error, key size must be <= 64\n");
|
printf2(TAG_ERR, "Error, key size must be <= 64\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,19 +151,24 @@ void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
|||||||
void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
||||||
{
|
{
|
||||||
uint8_t buf[64];
|
uint8_t buf[64];
|
||||||
int i;
|
unsigned int i;
|
||||||
crypto_sha256_final(hmac);
|
crypto_sha256_final(hmac);
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
if (key == CRYPTO_MASTER_KEY)
|
if (key == CRYPTO_MASTER_KEY)
|
||||||
{
|
{
|
||||||
key = master_secret;
|
key = master_secret;
|
||||||
klen = sizeof(master_secret);
|
klen = sizeof(master_secret)/2;
|
||||||
|
}
|
||||||
|
else if (key == CRYPTO_TRANSPORT_KEY2)
|
||||||
|
{
|
||||||
|
key = transport_secret;
|
||||||
|
klen = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(klen > 64)
|
if(klen > 64)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"Error, key size must be <= 64\n");
|
printf2(TAG_ERR, "Error, key size must be <= 64\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memmove(buf, key, klen);
|
memmove(buf, key, klen);
|
||||||
@ -167,16 +185,16 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_init()
|
void crypto_ecc256_init(void)
|
||||||
{
|
{
|
||||||
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
||||||
_es256_curve = uECC_secp256r1();
|
_es256_curve = uECC_secp256r1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_load_attestation_key()
|
void crypto_ecc256_load_attestation_key(void)
|
||||||
{
|
{
|
||||||
_signing_key = attestation_key;
|
_signing_key = device_get_attestation_key();
|
||||||
_key_len = 32;
|
_key_len = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +202,7 @@ void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
|
|||||||
{
|
{
|
||||||
if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0)
|
if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"error, uECC failed\n");
|
printf2(TAG_ERR, "error, uECC failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,19 +239,19 @@ void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_I
|
|||||||
if (_key_len != 32) goto fail;
|
if (_key_len != 32) goto fail;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf2(TAG_ERR,"error, invalid ECDSA alg specifier\n");
|
printf2(TAG_ERR, "error, invalid ECDSA alg specifier\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( uECC_sign(_signing_key, data, len, sig, curve) == 0)
|
if ( uECC_sign(_signing_key, data, len, sig, curve) == 0)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"error, uECC failed\n");
|
printf2(TAG_ERR, "error, uECC failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
printf2(TAG_ERR,"error, invalid key length\n");
|
printf2(TAG_ERR, "error, invalid key length\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -243,8 +261,11 @@ void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, ui
|
|||||||
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
|
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
|
||||||
crypto_sha256_update(data, len);
|
crypto_sha256_update(data, len);
|
||||||
crypto_sha256_update(data2, len2);
|
crypto_sha256_update(data2, len2);
|
||||||
crypto_sha256_update(master_secret, 32);
|
crypto_sha256_update(master_secret, 32); // TODO AES
|
||||||
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
|
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
|
||||||
|
|
||||||
|
crypto_aes256_init(master_secret + 32, NULL);
|
||||||
|
crypto_aes256_encrypt(privkey, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -261,12 +282,12 @@ void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8
|
|||||||
memmove(x,pubkey,32);
|
memmove(x,pubkey,32);
|
||||||
memmove(y,pubkey+32,32);
|
memmove(y,pubkey+32,32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_ecc256_compute_public_key(uint8_t * privkey, uint8_t * pubkey)
|
void crypto_ecc256_compute_public_key(uint8_t * privkey, uint8_t * pubkey)
|
||||||
{
|
{
|
||||||
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void crypto_load_external_key(uint8_t * key, int len)
|
void crypto_load_external_key(uint8_t * key, int len)
|
||||||
{
|
{
|
||||||
_signing_key = key;
|
_signing_key = key;
|
||||||
@ -278,7 +299,7 @@ void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey)
|
|||||||
{
|
{
|
||||||
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
|
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"Error, uECC_make_key failed\n");
|
printf2(TAG_ERR, "Error, uECC_make_key failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,7 +308,7 @@ void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey
|
|||||||
{
|
{
|
||||||
if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1)
|
if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"Error, uECC_shared_secret failed\n");
|
printf2(TAG_ERR, "Error, uECC_shared_secret failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,44 +359,4 @@ void crypto_aes256_encrypt(uint8_t * buf, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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"
|
|
||||||
"\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"
|
|
||||||
"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38"
|
|
||||||
"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32"
|
|
||||||
"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\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\x0f\x30\x0d"
|
|
||||||
"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55"
|
|
||||||
"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20"
|
|
||||||
"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72"
|
|
||||||
"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04"
|
|
||||||
"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07"
|
|
||||||
"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00"
|
|
||||||
"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf"
|
|
||||||
"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83"
|
|
||||||
"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca"
|
|
||||||
"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d"
|
|
||||||
"\xa1\x30\xa4\x2e\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\x06\x03\x55\x04"
|
|
||||||
"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94"
|
|
||||||
"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04"
|
|
||||||
"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00"
|
|
||||||
"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e"
|
|
||||||
"\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"
|
|
||||||
"\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 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 uint16_t attestation_key_size = sizeof(attestation_key)-1;
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error "No crypto implementation defined"
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define USE_SOFTWARE_IMPLEMENTATION
|
|
||||||
|
|
||||||
void crypto_sha256_init();
|
void crypto_sha256_init();
|
||||||
void crypto_sha256_update(uint8_t * data, size_t len);
|
void crypto_sha256_update(uint8_t * data, size_t len);
|
||||||
void crypto_sha256_update_secret();
|
void crypto_sha256_update_secret();
|
||||||
@ -23,7 +21,6 @@ void crypto_sha512_init();
|
|||||||
void crypto_sha512_update(const uint8_t * data, size_t len);
|
void crypto_sha512_update(const uint8_t * data, size_t len);
|
||||||
void crypto_sha512_final(uint8_t * hash);
|
void crypto_sha512_final(uint8_t * hash);
|
||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_init();
|
void crypto_ecc256_init();
|
||||||
void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y);
|
void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y);
|
||||||
void crypto_ecc256_compute_public_key(uint8_t * privkey, uint8_t * pubkey);
|
void crypto_ecc256_compute_public_key(uint8_t * privkey, uint8_t * pubkey);
|
||||||
@ -54,7 +51,4 @@ 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;
|
|
||||||
uint16_t attestation_cert_der_get_size();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
66
fido2/ctap.c
66
fido2/ctap.c
@ -69,6 +69,8 @@ uint8_t ctap_get_info(CborEncoder * encoder)
|
|||||||
CborEncoder map;
|
CborEncoder map;
|
||||||
CborEncoder options;
|
CborEncoder options;
|
||||||
CborEncoder pins;
|
CborEncoder pins;
|
||||||
|
uint8_t aaguid[16];
|
||||||
|
device_read_aaguid(aaguid);
|
||||||
|
|
||||||
ret = cbor_encoder_create_map(encoder, &map, 6);
|
ret = cbor_encoder_create_map(encoder, &map, 6);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
@ -105,7 +107,7 @@ uint8_t ctap_get_info(CborEncoder * encoder)
|
|||||||
ret = cbor_encode_uint(&map, RESP_aaguid);
|
ret = cbor_encode_uint(&map, RESP_aaguid);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
{
|
{
|
||||||
ret = cbor_encode_byte_string(&map, CTAP_AAGUID, 16);
|
ret = cbor_encode_byte_string(&map, aaguid, 16);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,13 +284,9 @@ void make_auth_tag(uint8_t * rpIdHash, uint8_t * nonce, uint32_t count, uint8_t
|
|||||||
memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE);
|
memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctap_flush_state(int backup)
|
void ctap_flush_state()
|
||||||
{
|
{
|
||||||
authenticator_write_state(&STATE, 0);
|
authenticator_write_state(&STATE);
|
||||||
if (backup)
|
|
||||||
{
|
|
||||||
authenticator_write_state(&STATE, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t auth_data_update_count(CTAP_authDataHeader * authData)
|
static uint32_t auth_data_update_count(CTAP_authDataHeader * authData)
|
||||||
@ -312,7 +310,7 @@ static uint32_t auth_data_update_count(CTAP_authDataHeader * authData)
|
|||||||
static void ctap_increment_rk_store()
|
static void ctap_increment_rk_store()
|
||||||
{
|
{
|
||||||
STATE.rk_stored++;
|
STATE.rk_stored++;
|
||||||
ctap_flush_state(1);
|
ctap_flush_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_matching_rk(CTAP_residentKey * rk, CTAP_residentKey * rk2)
|
static int is_matching_rk(CTAP_residentKey * rk, CTAP_residentKey * rk2)
|
||||||
@ -509,7 +507,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
|||||||
|
|
||||||
cbor_encoder_init(&cose_key, cose_key_buf, *len - sizeof(CTAP_authData), 0);
|
cbor_encoder_init(&cose_key, cose_key_buf, *len - sizeof(CTAP_authData), 0);
|
||||||
|
|
||||||
memmove(authData->attest.aaguid, CTAP_AAGUID, 16);
|
device_read_aaguid(authData->attest.aaguid);
|
||||||
authData->attest.credLenL = sizeof(CredentialId) & 0x00FF;
|
authData->attest.credLenL = sizeof(CredentialId) & 0x00FF;
|
||||||
authData->attest.credLenH = (sizeof(CredentialId) & 0xFF00) >> 8;
|
authData->attest.credLenH = (sizeof(CredentialId) & 0xFF00) >> 8;
|
||||||
|
|
||||||
@ -634,11 +632,17 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa
|
|||||||
uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
|
uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
uint8_t cert[1024];
|
||||||
|
uint16_t cert_size = device_attestation_cert_der_get_size();
|
||||||
|
if (cert_size > sizeof(cert)){
|
||||||
|
printf2(TAG_ERR,"Certificate is too large for CTAP2 buffer\r\n");
|
||||||
|
return CTAP2_ERR_PROCESSING;
|
||||||
|
}
|
||||||
|
device_attestation_read_cert_der(cert);
|
||||||
|
|
||||||
CborEncoder stmtmap;
|
CborEncoder stmtmap;
|
||||||
CborEncoder x5carr;
|
CborEncoder x5carr;
|
||||||
|
|
||||||
|
|
||||||
ret = cbor_encode_int(map,RESP_attStmt);
|
ret = cbor_encode_int(map,RESP_attStmt);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
ret = cbor_encoder_create_map(map, &stmtmap, 3);
|
ret = cbor_encoder_create_map(map, &stmtmap, 3);
|
||||||
@ -661,7 +665,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, cert, device_attestation_cert_der_get_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);
|
||||||
@ -1770,8 +1774,7 @@ static void ctap_state_init()
|
|||||||
*/
|
*/
|
||||||
void ctap_load_external_keys(uint8_t * keybytes){
|
void ctap_load_external_keys(uint8_t * keybytes){
|
||||||
memmove(STATE.key_space, keybytes, KEY_SPACE_BYTES);
|
memmove(STATE.key_space, keybytes, KEY_SPACE_BYTES);
|
||||||
authenticator_write_state(&STATE, 0);
|
authenticator_write_state(&STATE);
|
||||||
authenticator_write_state(&STATE, 1);
|
|
||||||
crypto_load_master_secret(STATE.key_space);
|
crypto_load_master_secret(STATE.key_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1785,30 +1788,18 @@ void ctap_init()
|
|||||||
);
|
);
|
||||||
crypto_ecc256_init();
|
crypto_ecc256_init();
|
||||||
|
|
||||||
authenticator_read_state(&STATE);
|
int is_init = authenticator_read_state(&STATE);
|
||||||
|
|
||||||
device_set_status(CTAPHID_STATUS_IDLE);
|
device_set_status(CTAPHID_STATUS_IDLE);
|
||||||
|
|
||||||
if (STATE.is_initialized == INITIALIZED_MARKER)
|
if (is_init)
|
||||||
{
|
{
|
||||||
printf1(TAG_STOR,"Auth state is initialized\n");
|
printf1(TAG_STOR,"Auth state is initialized\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf1(TAG_STOR,"Auth state is NOT initialized. Initializing..\n");
|
ctap_state_init();
|
||||||
if (authenticator_is_backup_initialized())
|
authenticator_write_state(&STATE);
|
||||||
{
|
|
||||||
printf1(TAG_ERR,"Warning: memory corruption detected. restoring from backup..\n");
|
|
||||||
authenticator_read_backup_state(&STATE);
|
|
||||||
authenticator_write_state(&STATE, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ctap_state_init();
|
|
||||||
authenticator_write_state(&STATE, 0);
|
|
||||||
authenticator_write_state(&STATE, 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do_migration_if_required(&STATE);
|
do_migration_if_required(&STATE);
|
||||||
@ -1875,8 +1866,7 @@ void ctap_update_pin(uint8_t * pin, int len)
|
|||||||
|
|
||||||
STATE.is_pin_set = 1;
|
STATE.is_pin_set = 1;
|
||||||
|
|
||||||
authenticator_write_state(&STATE, 1);
|
authenticator_write_state(&STATE);
|
||||||
authenticator_write_state(&STATE, 0);
|
|
||||||
|
|
||||||
printf1(TAG_CTAP, "New pin set: %s [%d]\n", pin, len);
|
printf1(TAG_CTAP, "New pin set: %s [%d]\n", pin, len);
|
||||||
dump_hex1(TAG_ERR, STATE.PIN_CODE_HASH, sizeof(STATE.PIN_CODE_HASH));
|
dump_hex1(TAG_ERR, STATE.PIN_CODE_HASH, sizeof(STATE.PIN_CODE_HASH));
|
||||||
@ -1891,7 +1881,7 @@ uint8_t ctap_decrement_pin_attempts()
|
|||||||
if (! ctap_device_locked())
|
if (! ctap_device_locked())
|
||||||
{
|
{
|
||||||
STATE.remaining_tries--;
|
STATE.remaining_tries--;
|
||||||
ctap_flush_state(0);
|
ctap_flush_state();
|
||||||
printf1(TAG_CP, "ATTEMPTS left: %d\n", STATE.remaining_tries);
|
printf1(TAG_CP, "ATTEMPTS left: %d\n", STATE.remaining_tries);
|
||||||
|
|
||||||
if (ctap_device_locked())
|
if (ctap_device_locked())
|
||||||
@ -1926,7 +1916,7 @@ void ctap_reset_pin_attempts()
|
|||||||
{
|
{
|
||||||
STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS;
|
STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS;
|
||||||
PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
|
PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
|
||||||
ctap_flush_state(0);
|
ctap_flush_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctap_reset_state()
|
void ctap_reset_state()
|
||||||
@ -2000,7 +1990,7 @@ int8_t ctap_store_key(uint8_t index, uint8_t * key, uint16_t len)
|
|||||||
|
|
||||||
memmove(STATE.key_space + offset, key, len);
|
memmove(STATE.key_space + offset, key, len);
|
||||||
|
|
||||||
ctap_flush_state(1);
|
ctap_flush_state();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2042,8 +2032,7 @@ void ctap_reset()
|
|||||||
{
|
{
|
||||||
ctap_state_init();
|
ctap_state_init();
|
||||||
|
|
||||||
authenticator_write_state(&STATE, 0);
|
authenticator_write_state(&STATE);
|
||||||
authenticator_write_state(&STATE, 1);
|
|
||||||
|
|
||||||
if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1)
|
if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1)
|
||||||
{
|
{
|
||||||
@ -2063,6 +2052,5 @@ void lock_device_permanently() {
|
|||||||
|
|
||||||
printf1(TAG_CP, "Device locked!\n");
|
printf1(TAG_CP, "Device locked!\n");
|
||||||
|
|
||||||
authenticator_write_state(&STATE, 0);
|
authenticator_write_state(&STATE);
|
||||||
authenticator_write_state(&STATE, 1);
|
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
#define CTAP_VENDOR_FIRST 0x40
|
#define CTAP_VENDOR_FIRST 0x40
|
||||||
#define CTAP_VENDOR_LAST 0xBF
|
#define CTAP_VENDOR_LAST 0xBF
|
||||||
|
|
||||||
// AAGUID For Solo
|
|
||||||
#define CTAP_AAGUID ((uint8_t*)"\x88\x76\x63\x1b\xd4\xa0\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79")
|
|
||||||
|
|
||||||
#define MC_clientDataHash 0x01
|
#define MC_clientDataHash 0x01
|
||||||
#define MC_rp 0x02
|
#define MC_rp 0x02
|
||||||
#define MC_user 0x03
|
#define MC_user 0x03
|
||||||
|
@ -275,7 +275,7 @@ static void ctaphid_write(CTAPHID_WRITE_BUFFER * wb, void * _data, int len)
|
|||||||
if (wb->offset > 0)
|
if (wb->offset > 0)
|
||||||
{
|
{
|
||||||
memset(wb->buf + wb->offset, 0, HID_MESSAGE_SIZE - wb->offset);
|
memset(wb->buf + wb->offset, 0, HID_MESSAGE_SIZE - wb->offset);
|
||||||
ctaphid_write_block(wb->buf);
|
usbhid_send(wb->buf);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -304,7 +304,7 @@ static void ctaphid_write(CTAPHID_WRITE_BUFFER * wb, void * _data, int len)
|
|||||||
wb->bytes_written += 1;
|
wb->bytes_written += 1;
|
||||||
if (wb->offset == HID_MESSAGE_SIZE)
|
if (wb->offset == HID_MESSAGE_SIZE)
|
||||||
{
|
{
|
||||||
ctaphid_write_block(wb->buf);
|
usbhid_send(wb->buf);
|
||||||
wb->offset = 0;
|
wb->offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -635,6 +635,9 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
status = ctap_request(ctap_buffer, len, &ctap_resp);
|
status = ctap_request(ctap_buffer, len, &ctap_resp);
|
||||||
|
|
||||||
wb.bcnt = (ctap_resp.length+1);
|
wb.bcnt = (ctap_resp.length+1);
|
||||||
|
wb.cid = cid;
|
||||||
|
wb.cmd = cmd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
timestamp();
|
timestamp();
|
||||||
@ -665,6 +668,9 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
|
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
|
||||||
|
|
||||||
wb.bcnt = (ctap_resp.length);
|
wb.bcnt = (ctap_resp.length);
|
||||||
|
wb.cid = cid;
|
||||||
|
wb.cmd = cmd;
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -59,6 +59,8 @@
|
|||||||
|
|
||||||
#define CTAP_CAPABILITIES (CAPABILITY_WINK | CAPABILITY_CBOR)
|
#define CTAP_CAPABILITIES (CAPABILITY_WINK | CAPABILITY_CBOR)
|
||||||
|
|
||||||
|
#define HID_MESSAGE_SIZE 64
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t cid;
|
uint32_t cid;
|
||||||
|
@ -56,8 +56,7 @@ bool migrate_from_FF_to_01(AuthenticatorState_0xFF* state_prev_0xff, Authenticat
|
|||||||
|
|
||||||
void save_migrated_state(AuthenticatorState *state_tmp_ptr) {
|
void save_migrated_state(AuthenticatorState *state_tmp_ptr) {
|
||||||
memmove(&STATE, state_tmp_ptr, sizeof(AuthenticatorState));
|
memmove(&STATE, state_tmp_ptr, sizeof(AuthenticatorState));
|
||||||
authenticator_write_state(state_tmp_ptr, 0);
|
authenticator_write_state(state_tmp_ptr);
|
||||||
authenticator_write_state(state_tmp_ptr, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_migration_if_required(AuthenticatorState* state_current){
|
void do_migration_if_required(AuthenticatorState* state_current){
|
||||||
|
209
fido2/device.c
Normal file
209
fido2/device.c
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
// Copyright 2019 SoloKeys Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||||
|
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||||
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||||
|
// copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
/** device.c
|
||||||
|
*
|
||||||
|
* This contains (weak) implementations
|
||||||
|
* to get FIDO2 working initially on a device. They probably
|
||||||
|
* aren't what you want to keep, but are designed to be replaced
|
||||||
|
* with some other platform specific implementation.
|
||||||
|
*
|
||||||
|
* For real examples, see the STM32L4 implementation and the PC implementation of device.c.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "ctaphid.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include APP_CONFIG
|
||||||
|
|
||||||
|
#define RK_NUM 50
|
||||||
|
|
||||||
|
struct ResidentKeyStore {
|
||||||
|
CTAP_residentKey rks[RK_NUM];
|
||||||
|
} RK_STORE;
|
||||||
|
|
||||||
|
|
||||||
|
static bool _up_disabled = false;
|
||||||
|
|
||||||
|
static 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"
|
||||||
|
"\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"
|
||||||
|
"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38"
|
||||||
|
"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32"
|
||||||
|
"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\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\x0f\x30\x0d"
|
||||||
|
"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55"
|
||||||
|
"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20"
|
||||||
|
"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72"
|
||||||
|
"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04"
|
||||||
|
"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07"
|
||||||
|
"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00"
|
||||||
|
"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf"
|
||||||
|
"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83"
|
||||||
|
"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca"
|
||||||
|
"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d"
|
||||||
|
"\xa1\x30\xa4\x2e\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\x06\x03\x55\x04"
|
||||||
|
"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94"
|
||||||
|
"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04"
|
||||||
|
"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00"
|
||||||
|
"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e"
|
||||||
|
"\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"
|
||||||
|
"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7";
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_attestation_read_cert_der(uint8_t * dst){
|
||||||
|
memmove(dst, _attestation_cert_der, device_attestation_cert_der_get_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint8_t * device_get_attestation_key(){
|
||||||
|
static 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";
|
||||||
|
return attestation_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint16_t device_attestation_cert_der_get_size(){
|
||||||
|
return sizeof(_attestation_cert_der)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_reboot()
|
||||||
|
{
|
||||||
|
printf1(TAG_RED, "REBOOT command recieved!\r\n");
|
||||||
|
exit(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_set_status(uint32_t status)
|
||||||
|
{
|
||||||
|
static uint32_t __device_status = 0;
|
||||||
|
if (status != CTAPHID_STATUS_IDLE && __device_status != status)
|
||||||
|
{
|
||||||
|
ctaphid_update_status(status);
|
||||||
|
}
|
||||||
|
__device_status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((weak)) void usbhid_close(){/**/}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_init(int argc, char *argv[]){/**/}
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_disable_up(bool disable)
|
||||||
|
{
|
||||||
|
_up_disabled = disable;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) int ctap_user_presence_test(uint32_t d)
|
||||||
|
{
|
||||||
|
if (_up_disabled)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) int ctap_user_verification(uint8_t arg)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t ctap_atomic_count(uint32_t amount)
|
||||||
|
{
|
||||||
|
static uint32_t counter1 = 25;
|
||||||
|
counter1 += (amount + 1);
|
||||||
|
return counter1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((weak)) int ctap_generate_rng(uint8_t * dst, size_t num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
printf1(TAG_ERR, "Insecure RNG being used.\r\n");
|
||||||
|
for (i = 0; i < num; i++){
|
||||||
|
dst[i] = (uint8_t)rand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) int device_is_nfc()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_wink()
|
||||||
|
{
|
||||||
|
printf1(TAG_GREEN,"*WINK*\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_set_clock_rate(DEVICE_CLOCK_RATE param){/**/}
|
||||||
|
|
||||||
|
static AuthenticatorState _tmp_state = {0};
|
||||||
|
__attribute__((weak)) int authenticator_read_state(AuthenticatorState * s){
|
||||||
|
if (_tmp_state.is_initialized != INITIALIZED_MARKER){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memmove(s, &_tmp_state, sizeof(AuthenticatorState));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void authenticator_write_state(AuthenticatorState * s){
|
||||||
|
memmove(&_tmp_state, s, sizeof(AuthenticatorState));
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void ctap_reset_rk()
|
||||||
|
{
|
||||||
|
memset(&RK_STORE,0xff,sizeof(RK_STORE));
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) uint32_t ctap_rk_size()
|
||||||
|
{
|
||||||
|
return RK_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((weak)) void ctap_store_rk(int index, CTAP_residentKey * rk)
|
||||||
|
{
|
||||||
|
if (index < RK_NUM)
|
||||||
|
{
|
||||||
|
memmove(RK_STORE.rks + index, rk, sizeof(CTAP_residentKey));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf1(TAG_ERR,"Out of bounds for store_rk\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void ctap_load_rk(int index, CTAP_residentKey * rk)
|
||||||
|
{
|
||||||
|
memmove(rk, RK_STORE.rks + index, sizeof(CTAP_residentKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void ctap_overwrite_rk(int index, CTAP_residentKey * rk)
|
||||||
|
{
|
||||||
|
if (index < RK_NUM)
|
||||||
|
{
|
||||||
|
memmove(RK_STORE.rks + index, rk, sizeof(CTAP_residentKey));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf1(TAG_ERR,"Out of bounds for store_rk\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void device_read_aaguid(uint8_t * dst){
|
||||||
|
uint8_t * aaguid = (uint8_t *)"\x00\x76\x63\x1b\xd4\xa0\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79";
|
||||||
|
memmove(dst, aaguid, 16);
|
||||||
|
}
|
||||||
|
|
212
fido2/device.h
212
fido2/device.h
@ -9,82 +9,159 @@
|
|||||||
|
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
|
|
||||||
void device_init(int argc, char *argv[]);
|
/** Return a millisecond timestamp. Does not need to be synchronized to anything.
|
||||||
|
* *Optional* to compile, but will not calculate delays correctly without a correct implementation.
|
||||||
|
*/
|
||||||
uint32_t millis();
|
uint32_t millis();
|
||||||
|
|
||||||
void delay(uint32_t ms);
|
|
||||||
|
|
||||||
// HID message size in bytes
|
|
||||||
#define HID_MESSAGE_SIZE 64
|
|
||||||
|
|
||||||
void usbhid_init();
|
|
||||||
|
|
||||||
int usbhid_recv(uint8_t * msg);
|
|
||||||
|
|
||||||
|
/** Called by HIDUSB layer to write bytes to the USB HID interface endpoint.
|
||||||
|
* Will write 64 bytes at a time.
|
||||||
|
*
|
||||||
|
* @param msg Pointer to a 64 byte buffer containing a payload to be sent via USB HID.
|
||||||
|
*
|
||||||
|
* **Required** to compile and work for FIDO application.
|
||||||
|
*/
|
||||||
void usbhid_send(uint8_t * msg);
|
void usbhid_send(uint8_t * msg);
|
||||||
|
|
||||||
void usbhid_close();
|
|
||||||
|
|
||||||
void main_loop_delay();
|
|
||||||
|
|
||||||
void heartbeat();
|
|
||||||
|
|
||||||
|
/** Reboot / power reset the device.
|
||||||
|
* **Optional** this is not used for FIDO2, and simply won't do anything if not implemented.
|
||||||
|
*/
|
||||||
void device_reboot();
|
void device_reboot();
|
||||||
|
|
||||||
void authenticator_read_state(AuthenticatorState * );
|
/** Read AuthenticatorState from nonvolatile memory.
|
||||||
|
* @param s pointer to AuthenticatorState buffer to be overwritten with contents from NV memory.
|
||||||
|
* @return 0 - state stored is NOT initialized.
|
||||||
|
* 1 - state stored is initialized.
|
||||||
|
*
|
||||||
|
* *Optional* this is required to make persistant updates to FIDO2 State (PIN and device master secret).
|
||||||
|
* Without it, changes simply won't be persistant.
|
||||||
|
*/
|
||||||
|
int authenticator_read_state(AuthenticatorState * s);
|
||||||
|
|
||||||
void authenticator_read_backup_state(AuthenticatorState * );
|
/** Store changes in the authenticator state to nonvolatile memory.
|
||||||
|
* @param s pointer to valid Authenticator state to write to NV memory.
|
||||||
// Return 1 yes backup is init'd, else 0
|
*
|
||||||
//void authenticator_initialize()
|
* *Optional* this is required to make persistant updates to FIDO2 State (PIN and device master secret).
|
||||||
int authenticator_is_backup_initialized();
|
* Without it, changes simply won't be persistant.
|
||||||
|
*/
|
||||||
void authenticator_write_state(AuthenticatorState *, int backup);
|
void authenticator_write_state(AuthenticatorState * s);
|
||||||
|
|
||||||
// Called each main loop. Doesn't need to do anything.
|
|
||||||
void device_manage();
|
|
||||||
|
|
||||||
// sets status that's uses for sending status updates ~100ms.
|
// sets status that's uses for sending status updates ~100ms.
|
||||||
// A timer should be set up to call `ctaphid_update_status`
|
// A timer should be set up to call `ctaphid_update_status`
|
||||||
|
|
||||||
|
/** Updates status of the status of the FIDO2 layer application, which
|
||||||
|
* can be used for polling updates in the USBHID layer.
|
||||||
|
*
|
||||||
|
* @param status is one of the following, which can be used appropriately by USB HID layer.
|
||||||
|
#define CTAPHID_STATUS_IDLE 0
|
||||||
|
#define CTAPHID_STATUS_PROCESSING 1
|
||||||
|
#define CTAPHID_STATUS_UPNEEDED 2
|
||||||
|
*
|
||||||
|
* *Optional* to compile and run, but will be required to be used for proper FIDO2 operation with some platforms.
|
||||||
|
*/
|
||||||
void device_set_status(uint32_t status);
|
void device_set_status(uint32_t status);
|
||||||
|
|
||||||
// Returns if button is currently pressed
|
/** Returns true if button is currently pressed. Debouncing does not need to be handled. Should not block.
|
||||||
|
* @return 1 if button is currently pressed.
|
||||||
|
*
|
||||||
|
* *Optional* to compile and run, but just returns one by default.
|
||||||
|
*/
|
||||||
int device_is_button_pressed();
|
int device_is_button_pressed();
|
||||||
|
|
||||||
// Test for user presence
|
//
|
||||||
// Return 2 for disabled, 1 for user is present, 0 user not present, -1 if cancel is requested.
|
// Return 2 for disabled, 1 for user is present, 0 user not present, -1 if cancel is requested.
|
||||||
|
/** Test for user presence.
|
||||||
|
* Perform test that user is present. Returns status on user presence. This is used by FIDO and U2F layer
|
||||||
|
* to check if an operation should continue, or if the UP flag should be set.
|
||||||
|
*
|
||||||
|
* @param delay number of milliseconds to delay waiting for user before timeout.
|
||||||
|
*
|
||||||
|
* @return 2 - User presence is disabled. Operation should continue, but UP flag not set.
|
||||||
|
* 1 - User presence confirmed. Operation should continue, and UP flag is set.
|
||||||
|
* 0 - User presence is not confirmed. Operation should be denied.
|
||||||
|
* -1 - Operation was canceled. Do not continue, reset transaction state.
|
||||||
|
*
|
||||||
|
* *Optional*, the default implementation will return 1, unless a FIDO2 operation calls for no UP, where this will then return 2.
|
||||||
|
*/
|
||||||
int ctap_user_presence_test(uint32_t delay);
|
int ctap_user_presence_test(uint32_t delay);
|
||||||
|
|
||||||
// Generate @num bytes of random numbers to @dest
|
/** Disable the next user presence test. This is called by FIDO2 layer when a transaction
|
||||||
// return 1 if success, error otherwise
|
* requests UP to be disabled. The next call to ctap_user_presence_test should return 2,
|
||||||
|
* and then UP should be enabled again.
|
||||||
|
*
|
||||||
|
* @param request_active indicate to activate (true) or disable (false) UP.
|
||||||
|
*
|
||||||
|
* *Optional*, the default implementation will provide expected behaviour with the default ctap_user_presence_test(...).
|
||||||
|
*/
|
||||||
|
void device_disable_up(bool request_active);
|
||||||
|
|
||||||
|
/** Generate random numbers. Random numbers should be good enough quality for
|
||||||
|
* cryptographic use.
|
||||||
|
*
|
||||||
|
* @param dst the buffer to write into.
|
||||||
|
* @param num the number of bytes to generate and write to dst.
|
||||||
|
*
|
||||||
|
* @return 1 if successful, or else the RNG failed.
|
||||||
|
*
|
||||||
|
* *Optional*, if not implemented, the random numbers will be from rand() and an error will be logged.
|
||||||
|
*/
|
||||||
int ctap_generate_rng(uint8_t * dst, size_t num);
|
int ctap_generate_rng(uint8_t * dst, size_t num);
|
||||||
|
|
||||||
// Increment atomic counter and return it.
|
/** Increment an atomic (non-volatile) counter and return the value.
|
||||||
// @param amount the amount to increase the counter by.
|
*
|
||||||
|
* @param amount a non-zero amount to increment the counter by.
|
||||||
|
*
|
||||||
|
* *Optional*, if not implemented, the counter will not be persistant.
|
||||||
|
*/
|
||||||
uint32_t ctap_atomic_count(uint32_t amount);
|
uint32_t ctap_atomic_count(uint32_t amount);
|
||||||
|
|
||||||
// Verify the user
|
/** Delete all resident keys.
|
||||||
// return 1 if user is verified, 0 if not
|
*
|
||||||
int ctap_user_verification(uint8_t arg);
|
* *Optional*, if not implemented, operates on non-persistant RK's.
|
||||||
|
*/
|
||||||
// Must be implemented by application
|
|
||||||
// data is HID_MESSAGE_SIZE long in bytes
|
|
||||||
void ctaphid_write_block(uint8_t * data);
|
|
||||||
|
|
||||||
|
|
||||||
// Resident key
|
|
||||||
void ctap_reset_rk();
|
void ctap_reset_rk();
|
||||||
|
|
||||||
|
/** Return the maximum amount of resident keys that can be stored.
|
||||||
|
* @return max number of resident keys that can be stored, including already stored RK's.
|
||||||
|
*
|
||||||
|
* *Optional*, if not implemented, returns 50.
|
||||||
|
*/
|
||||||
uint32_t ctap_rk_size();
|
uint32_t ctap_rk_size();
|
||||||
|
|
||||||
|
/** Store a resident key into an index between [ 0, ctap_rk_size() ).
|
||||||
|
* Storage should be in non-volatile memory.
|
||||||
|
*
|
||||||
|
* @param index between RK index range.
|
||||||
|
* @param rk pointer to valid rk structure that should be written to NV memory.
|
||||||
|
*
|
||||||
|
* *Optional*, if not implemented, operates on non-persistant RK's.
|
||||||
|
*/
|
||||||
void ctap_store_rk(int index,CTAP_residentKey * rk);
|
void ctap_store_rk(int index,CTAP_residentKey * rk);
|
||||||
|
|
||||||
|
/** Read a resident key from an index into memory
|
||||||
|
* @param index to read resident key from.
|
||||||
|
* @param rk pointer to resident key structure to write into with RK.
|
||||||
|
*
|
||||||
|
* *Optional*, if not implemented, operates on non-persistant RK's.
|
||||||
|
*/
|
||||||
void ctap_load_rk(int index,CTAP_residentKey * rk);
|
void ctap_load_rk(int index,CTAP_residentKey * rk);
|
||||||
|
|
||||||
|
/** Overwrite the RK located in index with a new RK.
|
||||||
|
* @param index to write resident key to.
|
||||||
|
* @param rk pointer to valid rk structure that should be written to NV memory, and replace existing RK there.
|
||||||
|
*
|
||||||
|
* *Optional*, if not implemented, operates on non-persistant RK's.
|
||||||
|
*/
|
||||||
void ctap_overwrite_rk(int index,CTAP_residentKey * rk);
|
void ctap_overwrite_rk(int index,CTAP_residentKey * rk);
|
||||||
|
|
||||||
// For Solo hacker
|
|
||||||
void boot_solo_bootloader();
|
|
||||||
void boot_st_bootloader();
|
|
||||||
|
|
||||||
// HID wink command
|
/** Called by HID layer to indicate that a wink behavior should be performed.
|
||||||
|
* Should not block, and the wink behavior should occur in parallel to FIDO operations.
|
||||||
|
*
|
||||||
|
* *Optional*.
|
||||||
|
*/
|
||||||
void device_wink();
|
void device_wink();
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -93,21 +170,50 @@ typedef enum {
|
|||||||
DEVICE_FAST = 2,
|
DEVICE_FAST = 2,
|
||||||
} DEVICE_CLOCK_RATE;
|
} DEVICE_CLOCK_RATE;
|
||||||
|
|
||||||
// Set the clock rate for the device.
|
/**
|
||||||
// Three modes are targetted for Solo.
|
* Set the clock rate for the device. This gets called only when the device is running in NFC mode.
|
||||||
// 0: Lowest clock rate for NFC.
|
* Before Register and authenticate operations, the clock rate will be set to (1), and otherwise back to (0).
|
||||||
// 1: fastest clock rate supported at a low power setting for NFC FIDO.
|
* @param param
|
||||||
// 2: fastest clock rate. Generally for USB interface.
|
0: Lowest clock rate for NFC.
|
||||||
|
1: fastest clock rate supported at a low power setting for NFC FIDO.
|
||||||
|
2: fastest clock rate. Generally for USB interface.
|
||||||
|
* *Optional*, by default nothing happens.
|
||||||
|
*/
|
||||||
void device_set_clock_rate(DEVICE_CLOCK_RATE param);
|
void device_set_clock_rate(DEVICE_CLOCK_RATE param);
|
||||||
|
|
||||||
// Returns NFC_IS_NA, NFC_IS_ACTIVE, or NFC_IS_AVAILABLE
|
// Returns NFC_IS_NA, NFC_IS_ACTIVE, or NFC_IS_AVAILABLE
|
||||||
#define NFC_IS_NA 0
|
#define NFC_IS_NA 0
|
||||||
#define NFC_IS_ACTIVE 1
|
#define NFC_IS_ACTIVE 1
|
||||||
#define NFC_IS_AVAILABLE 2
|
#define NFC_IS_AVAILABLE 2
|
||||||
|
|
||||||
|
/** Returns NFC status of the device.
|
||||||
|
* @return 0 - NFC is not available.
|
||||||
|
* 1 - NFC is active, and is powering the chip for a transaction.
|
||||||
|
* 2 - NFC is available, but not currently being used.
|
||||||
|
*/
|
||||||
int device_is_nfc();
|
int device_is_nfc();
|
||||||
|
|
||||||
void device_disable_up(bool request_active);
|
|
||||||
|
|
||||||
void device_init_button();
|
/** Return pointer to attestation key.
|
||||||
|
* @return pointer to attestation private key, raw encoded. For P256, this is 32 bytes.
|
||||||
|
*/
|
||||||
|
uint8_t * device_get_attestation_key();
|
||||||
|
|
||||||
|
/** Read the device's attestation certificate into buffer @dst.
|
||||||
|
* @param dst the destination to write the certificate.
|
||||||
|
*
|
||||||
|
* The size of the certificate can be retrieved using `device_attestation_cert_der_get_size()`.
|
||||||
|
*/
|
||||||
|
void device_attestation_read_cert_der(uint8_t * dst);
|
||||||
|
|
||||||
|
/** Returns the size in bytes of attestation_cert_der.
|
||||||
|
* @return number of bytes in attestation_cert_der, not including any C string null byte.
|
||||||
|
*/
|
||||||
|
uint16_t device_attestation_cert_der_get_size();
|
||||||
|
|
||||||
|
/** Read the device's 16 byte AAGUID into a buffer.
|
||||||
|
* @param dst buffer to write 16 byte AAGUID into.
|
||||||
|
* */
|
||||||
|
void device_read_aaguid(uint8_t * dst);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
41
fido2/example_app.h
Normal file
41
fido2/example_app.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2019 SoloKeys Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||||
|
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||||
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||||
|
// copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
#ifndef SRC_APP_H_
|
||||||
|
#define SRC_APP_H_
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define USING_DEV_BOARD
|
||||||
|
|
||||||
|
#define USING_PC
|
||||||
|
|
||||||
|
#define ENABLE_U2F
|
||||||
|
#define ENABLE_U2F_EXTENSIONS
|
||||||
|
//#define BRIDGE_TO_WALLET
|
||||||
|
|
||||||
|
void printing_init();
|
||||||
|
|
||||||
|
extern bool use_udp;
|
||||||
|
|
||||||
|
// 0xRRGGBB
|
||||||
|
#define LED_INIT_VALUE 0x000800
|
||||||
|
#define LED_WINK_VALUE 0x000008
|
||||||
|
#define LED_MAX_SCALER 30
|
||||||
|
#define LED_MIN_SCALER 1
|
||||||
|
// # of ms between each change in LED
|
||||||
|
#define HEARTBEAT_PERIOD 100
|
||||||
|
// Each LED channel will be multiplied by a integer between LED_MAX_SCALER
|
||||||
|
// and LED_MIN_SCALER to cause the slow pulse. E.g.
|
||||||
|
// #define LED_INIT_VALUE 0x301000
|
||||||
|
// #define LED_MAX_SCALER 30
|
||||||
|
// #define LED_MIN_SCALER 1
|
||||||
|
// #define HEARTBEAT_PERIOD 8
|
||||||
|
// Will pulse from 0x301000 to 0x903000 to 0x301000 ...
|
||||||
|
// Which will take ~8 * (30)*2 ms
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SRC_APP_H_ */
|
@ -7,7 +7,10 @@
|
|||||||
#ifndef _LOG_H
|
#ifndef _LOG_H
|
||||||
#define _LOG_H
|
#define _LOG_H
|
||||||
|
|
||||||
|
#ifdef APP_CONFIG
|
||||||
#include APP_CONFIG
|
#include APP_CONFIG
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifndef DEBUG_LEVEL
|
#ifndef DEBUG_LEVEL
|
||||||
@ -50,7 +53,7 @@ typedef enum
|
|||||||
TAG_FILENO = (1UL << 31)
|
TAG_FILENO = (1UL << 31)
|
||||||
} LOG_TAG;
|
} LOG_TAG;
|
||||||
|
|
||||||
#if DEBUG_LEVEL > 0
|
#if defined(DEBUG_LEVEL) && DEBUG_LEVEL > 0
|
||||||
|
|
||||||
void set_logging_mask(uint32_t mask);
|
void set_logging_mask(uint32_t mask);
|
||||||
#define printf1(tag,fmt, ...) LOG(tag & ~(TAG_FILENO), NULL, 0, fmt, ##__VA_ARGS__)
|
#define printf1(tag,fmt, ...) LOG(tag & ~(TAG_FILENO), NULL, 0, fmt, ##__VA_ARGS__)
|
||||||
|
12
fido2/u2f.c
12
fido2/u2f.c
@ -299,14 +299,19 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
|||||||
static int16_t u2f_register(struct u2f_register_request * req)
|
static int16_t u2f_register(struct u2f_register_request * req)
|
||||||
{
|
{
|
||||||
uint8_t i[] = {0x0,U2F_EC_FMT_UNCOMPRESSED};
|
uint8_t i[] = {0x0,U2F_EC_FMT_UNCOMPRESSED};
|
||||||
|
uint8_t cert[1024];
|
||||||
struct u2f_key_handle key_handle;
|
struct u2f_key_handle key_handle;
|
||||||
uint8_t pubkey[64];
|
uint8_t pubkey[64];
|
||||||
uint8_t hash[32];
|
uint8_t hash[32];
|
||||||
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 = device_attestation_cert_der_get_size();
|
||||||
|
|
||||||
|
if (attest_size > sizeof(cert)){
|
||||||
|
printf2(TAG_ERR,"Certificate is too large for buffer\r\n");
|
||||||
|
return U2F_SW_INSUFFICIENT_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! ctap_user_presence_test(750))
|
if ( ! ctap_user_presence_test(750))
|
||||||
{
|
{
|
||||||
@ -341,7 +346,8 @@ static int16_t u2f_register(struct u2f_register_request * req)
|
|||||||
u2f_response_writeback(i,1);
|
u2f_response_writeback(i,1);
|
||||||
u2f_response_writeback((uint8_t*)&key_handle,U2F_KEY_HANDLE_SIZE);
|
u2f_response_writeback((uint8_t*)&key_handle,U2F_KEY_HANDLE_SIZE);
|
||||||
|
|
||||||
u2f_response_writeback(attestation_cert_der,attest_size);
|
device_attestation_read_cert_der(cert);
|
||||||
|
u2f_response_writeback(cert,attest_size);
|
||||||
|
|
||||||
dump_signature_der(sig);
|
dump_signature_der(sig);
|
||||||
|
|
||||||
|
9
fido2/version.mk
Normal file
9
fido2/version.mk
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
SOLO_VERSION_FULL?=$(shell git describe)
|
||||||
|
SOLO_VERSION:=$(shell python -c 'print("$(SOLO_VERSION_FULL)".split("-")[0])')
|
||||||
|
SOLO_VERSION_MAJ:=$(shell python -c 'print("$(SOLO_VERSION)".split(".")[0])')
|
||||||
|
SOLO_VERSION_MIN:=$(shell python -c 'print("$(SOLO_VERSION)".split(".")[1])')
|
||||||
|
SOLO_VERSION_PAT:=$(shell python -c 'print("$(SOLO_VERSION)".split(".")[2])')
|
||||||
|
|
||||||
|
SOLO_VERSION_FLAGS := -DSOLO_VERSION_MAJ=$(SOLO_VERSION_MAJ) -DSOLO_VERSION_MIN=$(SOLO_VERSION_MIN) \
|
||||||
|
-DSOLO_VERSION_PATCH=$(SOLO_VERSION_PAT) -DSOLO_VERSION=\"$(SOLO_VERSION_FULL)\"
|
@ -15,8 +15,7 @@
|
|||||||
"authenticationAlgorithm": 1,
|
"authenticationAlgorithm": 1,
|
||||||
"publicKeyAlgAndEncoding": 260,
|
"publicKeyAlgAndEncoding": 260,
|
||||||
"attestationTypes": [
|
"attestationTypes": [
|
||||||
15879,
|
15879
|
||||||
15880
|
|
||||||
],
|
],
|
||||||
"userVerificationDetails": [
|
"userVerificationDetails": [
|
||||||
[
|
[
|
||||||
|
41
metadata/SoloTap-FIDO2-CTAP2-Authenticator.json
Normal file
41
metadata/SoloTap-FIDO2-CTAP2-Authenticator.json
Normal file
File diff suppressed because one or more lines are too long
41
metadata/Somu-FIDO2-CTAP2-Authenticator.json
Normal file
41
metadata/Somu-FIDO2-CTAP2-Authenticator.json
Normal file
File diff suppressed because one or more lines are too long
@ -18,6 +18,7 @@ nav:
|
|||||||
- Application Ideas: solo/application-ideas.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
|
||||||
|
- Usage and Porting guide: solo/porting.md
|
||||||
- Code documentation: solo/code-overview.md
|
- Code documentation: solo/code-overview.md
|
||||||
- Contributing Code: solo/contributing.md
|
- Contributing Code: solo/contributing.md
|
||||||
- Contributing Docs: solo/documenting.md
|
- Contributing Docs: solo/documenting.md
|
||||||
|
199
pc/device.c
199
pc/device.c
@ -11,7 +11,6 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -25,8 +24,7 @@
|
|||||||
|
|
||||||
#define RK_NUM 50
|
#define RK_NUM 50
|
||||||
|
|
||||||
bool use_udp = true;
|
static bool use_udp = true;
|
||||||
static bool _up_disabled = false;
|
|
||||||
|
|
||||||
struct ResidentKeyStore {
|
struct ResidentKeyStore {
|
||||||
CTAP_residentKey rks[RK_NUM];
|
CTAP_residentKey rks[RK_NUM];
|
||||||
@ -34,21 +32,6 @@ struct ResidentKeyStore {
|
|||||||
|
|
||||||
void authenticator_initialize();
|
void authenticator_initialize();
|
||||||
|
|
||||||
uint32_t __device_status = 0;
|
|
||||||
void device_set_status(uint32_t status)
|
|
||||||
{
|
|
||||||
if (status != CTAPHID_STATUS_IDLE && __device_status != status)
|
|
||||||
{
|
|
||||||
ctaphid_update_status(status);
|
|
||||||
}
|
|
||||||
__device_status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_reboot()
|
|
||||||
{
|
|
||||||
printf1(TAG_RED, "REBOOT command recieved!\r\n");
|
|
||||||
exit(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
int udp_server()
|
int udp_server()
|
||||||
{
|
{
|
||||||
@ -192,7 +175,6 @@ int usbhid_recv(uint8_t * msg)
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send 64 byte USB HID message
|
|
||||||
void usbhid_send(uint8_t * msg)
|
void usbhid_send(uint8_t * msg)
|
||||||
{
|
{
|
||||||
if (use_udp)
|
if (use_udp)
|
||||||
@ -209,6 +191,8 @@ void usbhid_send(uint8_t * msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void usbhid_close()
|
void usbhid_close()
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -272,14 +256,6 @@ void device_init(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void main_loop_delay()
|
|
||||||
{
|
|
||||||
struct timespec ts;
|
|
||||||
ts.tv_sec = 0;
|
|
||||||
ts.tv_nsec = 1000*1000*100;
|
|
||||||
nanosleep(&ts,NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void delay(uint32_t ms)
|
void delay(uint32_t ms)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
@ -289,40 +265,6 @@ void delay(uint32_t ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void heartbeat()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ctaphid_write_block(uint8_t * data)
|
|
||||||
{
|
|
||||||
/*printf("<< "); dump_hex(data, 64);*/
|
|
||||||
usbhid_send(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ctap_user_presence_test(uint32_t d)
|
|
||||||
{
|
|
||||||
if (_up_disabled)
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ctap_user_verification(uint8_t arg)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t ctap_atomic_count(uint32_t amount)
|
|
||||||
{
|
|
||||||
static uint32_t counter1 = 25;
|
|
||||||
counter1 += (amount + 1);
|
|
||||||
return counter1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ctap_generate_rng(uint8_t * dst, size_t num)
|
int ctap_generate_rng(uint8_t * dst, size_t num)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -344,10 +286,9 @@ int ctap_generate_rng(uint8_t * dst, size_t num)
|
|||||||
|
|
||||||
|
|
||||||
const char * state_file = "authenticator_state.bin";
|
const char * state_file = "authenticator_state.bin";
|
||||||
const char * backup_file = "authenticator_state2.bin";
|
|
||||||
const char * rk_file = "resident_keys.bin";
|
const char * rk_file = "resident_keys.bin";
|
||||||
|
|
||||||
void authenticator_read_state(AuthenticatorState * state)
|
int authenticator_read_state(AuthenticatorState * state)
|
||||||
{
|
{
|
||||||
FILE * f;
|
FILE * f;
|
||||||
int ret;
|
int ret;
|
||||||
@ -366,104 +307,35 @@ void authenticator_read_state(AuthenticatorState * state)
|
|||||||
perror("fwrite");
|
perror("fwrite");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (state->is_initialized == INITIALIZED_MARKER)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void authenticator_read_backup_state(AuthenticatorState * state )
|
|
||||||
|
void authenticator_write_state(AuthenticatorState * state)
|
||||||
{
|
{
|
||||||
FILE * f;
|
FILE * f;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
f = fopen(backup_file, "rb");
|
f = fopen(state_file, "wb+");
|
||||||
if (f== NULL)
|
if (f== NULL)
|
||||||
{
|
{
|
||||||
perror("fopen");
|
perror("fopen");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
ret = fwrite(state, 1, sizeof(AuthenticatorState), f);
|
||||||
ret = fread(state, 1, sizeof(AuthenticatorState), f);
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if(ret != sizeof(AuthenticatorState))
|
if (ret != sizeof(AuthenticatorState))
|
||||||
{
|
|
||||||
perror("fwrite");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void authenticator_write_state(AuthenticatorState * state, int backup)
|
|
||||||
{
|
|
||||||
FILE * f;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (! backup)
|
|
||||||
{
|
|
||||||
f = fopen(state_file, "wb+");
|
|
||||||
if (f== NULL)
|
|
||||||
{
|
|
||||||
perror("fopen");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
ret = fwrite(state, 1, sizeof(AuthenticatorState), f);
|
|
||||||
fclose(f);
|
|
||||||
if (ret != sizeof(AuthenticatorState))
|
|
||||||
{
|
|
||||||
perror("fwrite");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
f = fopen(backup_file, "wb+");
|
|
||||||
if (f== NULL)
|
|
||||||
{
|
|
||||||
perror("fopen");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
ret = fwrite(state, 1, sizeof(AuthenticatorState), f);
|
|
||||||
fclose(f);
|
|
||||||
if (ret != sizeof(AuthenticatorState))
|
|
||||||
{
|
|
||||||
perror("fwrite");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return 1 yes backup is init'd, else 0
|
|
||||||
int authenticator_is_backup_initialized()
|
|
||||||
{
|
|
||||||
uint8_t header[16];
|
|
||||||
AuthenticatorState * state = (AuthenticatorState*) header;
|
|
||||||
FILE * f;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
printf("state file exists\n");
|
|
||||||
f = fopen(backup_file, "rb");
|
|
||||||
if (f== NULL)
|
|
||||||
{
|
|
||||||
printf("Warning, backup file doesn't exist\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = fread(header, 1, sizeof(header), f);
|
|
||||||
fclose(f);
|
|
||||||
if(ret != sizeof(header))
|
|
||||||
{
|
{
|
||||||
perror("fwrite");
|
perror("fwrite");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state->is_initialized == INITIALIZED_MARKER;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return 1 yes backup is init'd, else 0
|
|
||||||
/*int authenticator_is_initialized()*/
|
|
||||||
/*{*/
|
|
||||||
|
|
||||||
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
static void sync_rk()
|
static void sync_rk()
|
||||||
{
|
{
|
||||||
@ -543,44 +415,18 @@ void authenticator_initialize()
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen(backup_file, "wb+");
|
|
||||||
if (f== NULL)
|
|
||||||
{
|
|
||||||
perror("fopen");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
mem = malloc(sizeof(AuthenticatorState));
|
|
||||||
memset(mem,0xff,sizeof(AuthenticatorState));
|
|
||||||
ret = fwrite(mem, 1, sizeof(AuthenticatorState), f);
|
|
||||||
free(mem);
|
|
||||||
fclose(f);
|
|
||||||
if (ret != sizeof(AuthenticatorState))
|
|
||||||
{
|
|
||||||
perror("fwrite");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// resident_keys
|
// resident_keys
|
||||||
memset(&RK_STORE,0xff,sizeof(RK_STORE));
|
memset(&RK_STORE,0xff,sizeof(RK_STORE));
|
||||||
sync_rk();
|
sync_rk();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_manage()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ctap_reset_rk()
|
void ctap_reset_rk()
|
||||||
{
|
{
|
||||||
memset(&RK_STORE,0xff,sizeof(RK_STORE));
|
memset(&RK_STORE,0xff,sizeof(RK_STORE));
|
||||||
sync_rk();
|
sync_rk();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ctap_rk_size()
|
uint32_t ctap_rk_size()
|
||||||
@ -622,22 +468,9 @@ void ctap_overwrite_rk(int index, CTAP_residentKey * rk)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_wink()
|
|
||||||
{
|
|
||||||
printf("*WINK*\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int device_is_nfc()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_disable_up(bool disable)
|
|
||||||
{
|
|
||||||
_up_disabled = disable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_set_clock_rate(DEVICE_CLOCK_RATE param)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "cbor.h"
|
#include "cbor.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
@ -17,9 +18,12 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "ctap.h"
|
#include "ctap.h"
|
||||||
#include APP_CONFIG
|
#include "app.h"
|
||||||
|
|
||||||
|
|
||||||
|
void device_init(int argc, char *argv[]);
|
||||||
|
int usbhid_recv(uint8_t * msg);
|
||||||
|
|
||||||
#if !defined(TEST)
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@ -29,20 +33,21 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
set_logging_mask(
|
set_logging_mask(
|
||||||
/*0*/
|
/*0*/
|
||||||
//TAG_GEN|
|
// TAG_GEN|
|
||||||
// TAG_MC |
|
// TAG_MC |
|
||||||
// TAG_GA |
|
// TAG_GA |
|
||||||
TAG_WALLET |
|
TAG_WALLET |
|
||||||
TAG_STOR |
|
TAG_STOR |
|
||||||
//TAG_NFC_APDU |
|
//TAG_NFC_APDU |
|
||||||
TAG_NFC |
|
TAG_NFC |
|
||||||
//TAG_CP |
|
// TAG_CP |
|
||||||
// TAG_CTAP|
|
// TAG_CTAP|
|
||||||
//TAG_HID|
|
// TAG_HID|
|
||||||
TAG_U2F|
|
TAG_U2F|
|
||||||
//TAG_PARSE |
|
// TAG_PARSE |
|
||||||
//TAG_TIME|
|
//TAG_TIME|
|
||||||
// TAG_DUMP|
|
// TAG_DUMP|
|
||||||
|
// TAG_DUMP2|
|
||||||
TAG_GREEN|
|
TAG_GREEN|
|
||||||
TAG_RED|
|
TAG_RED|
|
||||||
TAG_EXT|
|
TAG_EXT|
|
||||||
@ -57,13 +62,6 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
if (millis() - t1 > HEARTBEAT_PERIOD)
|
|
||||||
{
|
|
||||||
heartbeat();
|
|
||||||
t1 = millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
device_manage();
|
|
||||||
|
|
||||||
if (usbhid_recv(hidmsg) > 0)
|
if (usbhid_recv(hidmsg) > 0)
|
||||||
{
|
{
|
||||||
@ -73,14 +71,16 @@ int main(int argc, char *argv[])
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ctaphid_check_timeouts();
|
ctaphid_check_timeouts();
|
||||||
|
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = 1000*1000*10;
|
||||||
|
nanosleep(&ts,NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should never get here
|
// Should never get here
|
||||||
usbhid_close();
|
|
||||||
printf1(TAG_GREEN, "done\n");
|
printf1(TAG_GREEN, "done\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
@ -9,6 +9,7 @@
|
|||||||
#define _APP_H_
|
#define _APP_H_
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "solo.h"
|
||||||
#define DEBUG_UART USART1
|
#define DEBUG_UART USART1
|
||||||
|
|
||||||
#ifndef DEBUG_LEVEL
|
#ifndef DEBUG_LEVEL
|
||||||
|
@ -2,14 +2,14 @@ include build/common.mk
|
|||||||
|
|
||||||
# ST related
|
# ST related
|
||||||
SRC = src/main.c src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
|
SRC = src/main.c src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
|
||||||
SRC += src/fifo.c src/crypto.c src/attestation.c src/nfc.c src/ams.c src/sense.c
|
SRC += src/fifo.c src/attestation.c src/nfc.c src/ams.c src/sense.c
|
||||||
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||||
SRC += $(DRIVER_LIBS) $(USB_LIB)
|
SRC += $(DRIVER_LIBS) $(USB_LIB)
|
||||||
|
|
||||||
# FIDO2 lib
|
# FIDO2 lib
|
||||||
SRC += ../../fido2/apdu.c ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c
|
SRC += ../../fido2/apdu.c ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c
|
||||||
SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c
|
SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c
|
||||||
SRC += ../../fido2/ctap_parse.c ../../fido2/main.c
|
SRC += ../../fido2/ctap_parse.c ../../fido2/crypto.c
|
||||||
SRC += ../../fido2/version.c
|
SRC += ../../fido2/version.c
|
||||||
SRC += ../../fido2/data_migration.c
|
SRC += ../../fido2/data_migration.c
|
||||||
SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c
|
SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c
|
||||||
@ -22,7 +22,9 @@ SRC += ../../crypto/cifra/src/sha512.c ../../crypto/cifra/src/blockwise.c
|
|||||||
OBJ1=$(SRC:.c=.o)
|
OBJ1=$(SRC:.c=.o)
|
||||||
OBJ=$(OBJ1:.s=.o)
|
OBJ=$(OBJ1:.s=.o)
|
||||||
|
|
||||||
INC = -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions
|
INC = -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/
|
||||||
|
|
||||||
|
INC+= -I../../fido2/ -I../../fido2/extensions
|
||||||
INC += -I../../tinycbor/src -I../../crypto/sha256 -I../../crypto/micro-ecc
|
INC += -I../../tinycbor/src -I../../crypto/sha256 -I../../crypto/micro-ecc
|
||||||
INC += -I../../crypto/tiny-AES-c
|
INC += -I../../crypto/tiny-AES-c
|
||||||
INC += -I../../crypto/cifra/src -I../../crypto/cifra/src/ext
|
INC += -I../../crypto/cifra/src -I../../crypto/cifra/src/ext
|
||||||
@ -66,9 +68,6 @@ all: $(TARGET).elf
|
|||||||
../../crypto/micro-ecc/uECC.o: ../../crypto/micro-ecc/uECC.c
|
../../crypto/micro-ecc/uECC.o: ../../crypto/micro-ecc/uECC.c
|
||||||
$(CC) $^ $(HW) -O3 $(ECC_CFLAGS) -o $@
|
$(CC) $^ $(HW) -O3 $(ECC_CFLAGS) -o $@
|
||||||
|
|
||||||
%.o: %.s
|
|
||||||
$(CC) $^ $(HW) -Os $(CFLAGS) -o $@
|
|
||||||
|
|
||||||
%.elf: $(OBJ)
|
%.elf: $(OBJ)
|
||||||
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
||||||
@echo "Built version: $(VERSION_FLAGS)"
|
@echo "Built version: $(VERSION_FLAGS)"
|
||||||
|
@ -4,13 +4,14 @@ include build/common.mk
|
|||||||
SRC = bootloader/main.c bootloader/bootloader.c
|
SRC = bootloader/main.c bootloader/bootloader.c
|
||||||
SRC += bootloader/pubkey_bootloader.c bootloader/version_check.c
|
SRC += bootloader/pubkey_bootloader.c bootloader/version_check.c
|
||||||
SRC += src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
|
SRC += src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
|
||||||
SRC += src/fifo.c src/crypto.c src/attestation.c src/sense.c
|
SRC += src/fifo.c src/attestation.c src/sense.c
|
||||||
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||||
SRC += $(DRIVER_LIBS) $(USB_LIB)
|
SRC += $(DRIVER_LIBS) $(USB_LIB)
|
||||||
|
|
||||||
# FIDO2 lib
|
# FIDO2 lib
|
||||||
SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/extensions/extensions.c
|
SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/extensions/extensions.c
|
||||||
SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c
|
SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c
|
||||||
|
SRC += ../../fido2/crypto.c
|
||||||
|
|
||||||
# Crypto libs
|
# Crypto libs
|
||||||
SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c
|
SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
|
include ../../fido2/version.mk
|
||||||
|
|
||||||
CC=$(PREFIX)arm-none-eabi-gcc
|
CC=$(PREFIX)arm-none-eabi-gcc
|
||||||
CP=$(PREFIX)arm-none-eabi-objcopy
|
CP=$(PREFIX)arm-none-eabi-objcopy
|
||||||
SZ=$(PREFIX)arm-none-eabi-size
|
SZ=$(PREFIX)arm-none-eabi-size
|
||||||
AR=$(PREFIX)arm-none-eabi-ar
|
AR=$(PREFIX)arm-none-eabi-ar
|
||||||
|
AS=$(PREFIX)arm-none-eabi-as
|
||||||
|
|
||||||
DRIVER_LIBS := lib/stm32l4xx_hal_pcd.c lib/stm32l4xx_hal_pcd_ex.c lib/stm32l4xx_ll_gpio.c \
|
DRIVER_LIBS := lib/stm32l4xx_hal_pcd.c lib/stm32l4xx_hal_pcd_ex.c lib/stm32l4xx_ll_gpio.c \
|
||||||
lib/stm32l4xx_ll_rcc.c lib/stm32l4xx_ll_rng.c lib/stm32l4xx_ll_tim.c \
|
lib/stm32l4xx_ll_rcc.c lib/stm32l4xx_ll_rng.c lib/stm32l4xx_ll_tim.c \
|
||||||
@ -13,17 +16,20 @@ 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_FULL?=$(SOLO_VERSION_FULL)
|
||||||
VERSION:=$(shell python -c 'print("$(VERSION_FULL)".split("-")[0])')
|
VERSION:=$(SOLO_VERSION)
|
||||||
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
|
VERSION_MAJ:=$(SOLO_VERSION_MAJ)
|
||||||
VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
|
VERSION_MIN:=$(SOLO_VERSION_MIN)
|
||||||
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
|
VERSION_PAT:=$(SOLO_VERSION_PAT)
|
||||||
|
|
||||||
VERSION_FLAGS= -DSOLO_VERSION_MAJ=$(VERSION_MAJ) -DSOLO_VERSION_MIN=$(VERSION_MIN) \
|
VERSION_FLAGS= -DSOLO_VERSION_MAJ=$(VERSION_MAJ) -DSOLO_VERSION_MIN=$(VERSION_MIN) \
|
||||||
-DSOLO_VERSION_PATCH=$(VERSION_PAT) -DSOLO_VERSION=\"$(VERSION_FULL)\"
|
-DSOLO_VERSION_PATCH=$(VERSION_PAT) -DSOLO_VERSION=\"$(VERSION_FULL)\"
|
||||||
|
|
||||||
_all:
|
_all:
|
||||||
echo $(VERSION_FULL)
|
echo $(SOLO_VERSION_FULL)
|
||||||
echo $(VERSION_MAJ)
|
echo $(SOLO_VERSION_MAJ)
|
||||||
echo $(VERSION_MIN)
|
echo $(SOLO_VERSION_MIN)
|
||||||
echo $(VERSION_PAT)
|
echo $(SOLO_VERSION_PAT)
|
||||||
|
|
||||||
|
%.o: %.s
|
||||||
|
$(AS) -o $@ $^
|
@ -8,6 +8,7 @@
|
|||||||
#define _APP_H_
|
#define _APP_H_
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "solo.h"
|
||||||
|
|
||||||
#define SOLO
|
#define SOLO
|
||||||
|
|
||||||
|
@ -5,12 +5,16 @@
|
|||||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||||
// 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 <string.h>
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "memory_layout.h"
|
#include "memory_layout.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "sense.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
const uint8_t attestation_solo_cert_der[] =
|
const uint8_t attestation_solo_cert_der[] =
|
||||||
"\x30\x82\x02\xe1\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
|
"\x30\x82\x03\x03\x30\x82\x02\xaa\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"
|
||||||
"\x61\x6e\x64\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x53\x6f\x6c\x6f\x20\x4b"
|
"\x61\x6e\x64\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x53\x6f\x6c\x6f\x20\x4b"
|
||||||
@ -18,36 +22,37 @@ const uint8_t attestation_solo_cert_der[] =
|
|||||||
"\x41\x31\x15\x30\x13\x06\x03\x55\x04\x03\x0c\x0c\x73\x6f\x6c\x6f\x6b\x65\x79\x73"
|
"\x41\x31\x15\x30\x13\x06\x03\x55\x04\x03\x0c\x0c\x73\x6f\x6c\x6f\x6b\x65\x79\x73"
|
||||||
"\x2e\x63\x6f\x6d\x31\x21\x30\x1f\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16"
|
"\x2e\x63\x6f\x6d\x31\x21\x30\x1f\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16"
|
||||||
"\x12\x68\x65\x6c\x6c\x6f\x40\x73\x6f\x6c\x6f\x6b\x65\x79\x73\x2e\x63\x6f\x6d\x30"
|
"\x12\x68\x65\x6c\x6c\x6f\x40\x73\x6f\x6c\x6f\x6b\x65\x79\x73\x2e\x63\x6f\x6d\x30"
|
||||||
"\x20\x17\x0d\x31\x38\x31\x31\x31\x31\x31\x32\x35\x32\x30\x30\x5a\x18\x0f\x32\x30"
|
"\x20\x17\x0d\x31\x39\x31\x32\x30\x31\x31\x39\x32\x33\x34\x39\x5a\x18\x0f\x32\x30"
|
||||||
"\x36\x38\x31\x30\x32\x39\x31\x32\x35\x32\x30\x30\x5a\x30\x81\x92\x31\x0b\x30\x09"
|
"\x36\x39\x31\x31\x31\x38\x31\x39\x32\x33\x34\x39\x5a\x30\x81\x91\x31\x0b\x30\x09"
|
||||||
"\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08"
|
"\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\x61\x6e\x64\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x53"
|
"\x4d\x61\x72\x79\x6c\x61\x6e\x64\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x0c\x08\x53"
|
||||||
"\x6f\x6c\x6f\x20\x4b\x65\x79\x73\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x0c\x19\x41"
|
"\x6f\x6c\x6f\x4b\x65\x79\x73\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x0c\x19\x41\x75"
|
||||||
"\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72\x20\x41\x74\x74\x65\x73\x74\x61"
|
"\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72\x20\x41\x74\x74\x65\x73\x74\x61\x74"
|
||||||
"\x74\x69\x6f\x6e\x31\x15\x30\x13\x06\x03\x55\x04\x03\x0c\x0c\x73\x6f\x6c\x6f\x6b"
|
"\x69\x6f\x6e\x31\x15\x30\x13\x06\x03\x55\x04\x03\x0c\x0c\x73\x6f\x6c\x6f\x6b\x65"
|
||||||
"\x65\x79\x73\x2e\x63\x6f\x6d\x31\x21\x30\x1f\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01"
|
|
||||||
"\x09\x01\x16\x12\x68\x65\x6c\x6c\x6f\x40\x73\x6f\x6c\x6f\x6b\x65\x79\x73\x2e\x63"
|
|
||||||
"\x6f\x6d\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
|
|
||||||
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x22\xfe\x0f\xb5\x2a\x78\xbe\xc6\x45\x37\x1a"
|
|
||||||
"\x28\xa7\x57\x43\x49\xa4\x6f\x85\x4d\xca\x4e\x25\x1c\x9f\x75\x30\x3d\xbf\x10\xd5"
|
|
||||||
"\xd2\xd2\x0b\xb9\x69\x2c\xdd\xb2\x5c\x14\xd8\x39\x85\x12\xf6\x23\xee\x91\xba\xc6"
|
|
||||||
"\xac\xff\x4a\x1a\x27\xef\xe0\xc1\x54\x3f\xd4\xd9\xc5\xa3\x81\xdc\x30\x81\xd9\x30"
|
|
||||||
"\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x3b\xe6\xd2\xc0\x6f\xf2\xe7\xb0\x7c\x9d"
|
|
||||||
"\x9e\x28\xc0\x20\xb0\x0d\x07\xc8\x15\xc8\x30\x81\x9f\x06\x03\x55\x1d\x23\x04\x81"
|
|
||||||
"\x97\x30\x81\x94\xa1\x81\x86\xa4\x81\x83\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\x61\x6e\x64\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x53\x6f\x6c\x6f"
|
|
||||||
"\x20\x4b\x65\x79\x73\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x0c\x07\x52\x6f\x6f\x74"
|
|
||||||
"\x20\x43\x41\x31\x15\x30\x13\x06\x03\x55\x04\x03\x0c\x0c\x73\x6f\x6c\x6f\x6b\x65"
|
|
||||||
"\x79\x73\x2e\x63\x6f\x6d\x31\x21\x30\x1f\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09"
|
"\x79\x73\x2e\x63\x6f\x6d\x31\x21\x30\x1f\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09"
|
||||||
"\x01\x16\x12\x68\x65\x6c\x6c\x6f\x40\x73\x6f\x6c\x6f\x6b\x65\x79\x73\x2e\x63\x6f"
|
"\x01\x16\x12\x68\x65\x6c\x6c\x6f\x40\x73\x6f\x6c\x6f\x6b\x65\x79\x73\x2e\x63\x6f"
|
||||||
"\x6d\x82\x09\x00\xc4\x47\x63\x92\x8f\xf4\xbe\x8c\x30\x09\x06\x03\x55\x1d\x13\x04"
|
"\x6d\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce"
|
||||||
"\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x04\xf0\x30\x0a\x06\x08"
|
"\x3d\x03\x01\x07\x03\x42\x00\x04\x22\xfe\x0f\xb5\x2a\x78\xbe\xc6\x45\x37\x1a\x28"
|
||||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x47\x00\x30\x44\x02\x20\x71\x10\x46\x2c\xf5"
|
"\xa7\x57\x43\x49\xa4\x6f\x85\x4d\xca\x4e\x25\x1c\x9f\x75\x30\x3d\xbf\x10\xd5\xd2"
|
||||||
"\x16\x18\x97\x55\xca\x64\x50\x3b\x69\xb2\xdf\x17\x71\xab\xad\x8e\xc0\xd6\xa6\x07"
|
"\xd2\x0b\xb9\x69\x2c\xdd\xb2\x5c\x14\xd8\x39\x85\x12\xf6\x23\xee\x91\xba\xc6\xac"
|
||||||
"\x3d\x66\x8a\x3b\xbb\xfe\x61\x02\x20\x1e\x82\xef\xeb\x5e\x4e\x3a\x00\x84\x64\xd2"
|
"\xff\x4a\x1a\x27\xef\xe0\xc1\x54\x3f\xd4\xd9\xc5\xa3\x81\xff\x30\x81\xfc\x30\x1d"
|
||||||
"\xf8\x84\xc3\x78\x35\x93\x63\x81\x2e\xbe\xa6\x12\x32\x6e\x29\x90\xc8\x91\x4b\x71"
|
"\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x3b\xe6\xd2\xc0\x6f\xf2\xe7\xb0\x7c\x9d\x9e"
|
||||||
"\x52"
|
"\x28\xc0\x20\xb0\x0d\x07\xc8\x15\xc8\x30\x81\x9f\x06\x03\x55\x1d\x23\x04\x81\x97"
|
||||||
|
"\x30\x81\x94\xa1\x81\x86\xa4\x81\x83\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\x61\x6e\x64\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x53\x6f\x6c\x6f\x20"
|
||||||
|
"\x4b\x65\x79\x73\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x0c\x07\x52\x6f\x6f\x74\x20"
|
||||||
|
"\x43\x41\x31\x15\x30\x13\x06\x03\x55\x04\x03\x0c\x0c\x73\x6f\x6c\x6f\x6b\x65\x79"
|
||||||
|
"\x73\x2e\x63\x6f\x6d\x31\x21\x30\x1f\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01"
|
||||||
|
"\x16\x12\x68\x65\x6c\x6c\x6f\x40\x73\x6f\x6c\x6f\x6b\x65\x79\x73\x2e\x63\x6f\x6d"
|
||||||
|
"\x82\x09\x00\xc4\x47\x63\x92\x8f\xf4\xbe\x8c\x30\x09\x06\x03\x55\x1d\x13\x04\x02"
|
||||||
|
"\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x04\xf0\x30\x21\x06\x0b\x2b"
|
||||||
|
"\x06\x01\x04\x01\x82\xe5\x1c\x01\x01\x04\x04\x12\x04\x10\x88\x76\x63\x1b\xd4\xa0"
|
||||||
|
"\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04"
|
||||||
|
"\x03\x02\x03\x47\x00\x30\x44\x02\x20\x4d\xea\x09\x15\x6c\x86\x48\x57\x2a\xa8\x8d"
|
||||||
|
"\x87\xc3\xfa\xb6\x6b\x29\x9b\xfb\x8b\x4d\x4d\x29\x77\x5b\xa1\x04\x4c\x7f\x12\x8d"
|
||||||
|
"\x71\x02\x20\x47\x4c\x3d\xb2\xa1\x74\xe3\x9c\xfe\xe1\x23\xbf\xec\x47\x96\xf4\xe5"
|
||||||
|
"\x9b\x65\x76\xac\xc8\x69\x1d\xe2\x74\xff\x4e\xa4\xcf\x02\x6d"
|
||||||
;
|
;
|
||||||
|
|
||||||
const uint8_t attestation_hacker_cert_der[] =
|
const uint8_t attestation_hacker_cert_der[] =
|
||||||
@ -95,12 +100,32 @@ const uint8_t attestation_hacker_cert_der[] =
|
|||||||
const uint16_t attestation_solo_cert_der_size = sizeof(attestation_solo_cert_der)-1;
|
const uint16_t attestation_solo_cert_der_size = sizeof(attestation_solo_cert_der)-1;
|
||||||
const uint16_t attestation_hacker_cert_der_size = sizeof(attestation_hacker_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"
|
uint8_t * device_get_attestation_key(){
|
||||||
uint16_t attestation_cert_der_get_size(){
|
flash_attestation_page * page =(flash_attestation_page *)ATTESTATION_PAGE_ADDR;
|
||||||
|
return page->attestation_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t device_attestation_cert_der_get_size(){
|
||||||
uint16_t sz = (uint16_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size;
|
uint16_t sz = (uint16_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size;
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void device_attestation_read_cert_der(uint8_t * dst){
|
||||||
|
const uint8_t * der = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert;
|
||||||
|
uint16_t sz = device_attestation_cert_der_get_size();
|
||||||
|
memmove(dst, der, sz);
|
||||||
|
|
||||||
|
// Overwrite respective x509 fields if Tap or Somu.
|
||||||
|
if (memcmp(dst + 0x2c6, "\xea\x09\x15\x6c\x86\x48\x57\x2a\xa8\x8d", 10) == 0){
|
||||||
|
if (device_is_nfc()){
|
||||||
|
dst[0x2a2] = 0x89;//tap aaguid byte
|
||||||
|
memmove(dst + 0xac, "\x34\x33\x38\x5a\x18\x0f\x32\x30\x36\x39\x31\x31\x31\x38\x31\x39\x32\x34\x33\x38", 20);//tap-id
|
||||||
|
memmove(dst + 0x2c5, "\x6d\x7b\x41\x2b\xff\x57\xf0\x03\xbd\x5b\x39\x4a\xf7\xa9\x2d\x6d\xcb\x9e\x2d\x88\xbf\xb3\x93\xc5\x66\x3b\xd1\xbc\x34\xfa\x5c\x4c\x02\x20\x59\x01\x49\x39\x1b\xb7\xa9\x1c\xed\x49\x78\x4f\x92\xa9\x61\x14\xa5\x6e\x96\x3f\x29\x02\x93\xe0\x5d\xe2\x75\xd0\x60\xd9\x74\xc2", 66);//tap-sig
|
||||||
|
} else if (tsc_sensor_exists()) {
|
||||||
|
dst[0x2a2] = 0x98;//somu aaguid byte
|
||||||
|
memmove(dst + 0xac, "\x35\x30\x32\x5a\x18\x0f\x32\x30\x36\x39\x31\x31\x31\x38\x31\x39\x32\x35\x30\x32", 20);//somu-id
|
||||||
|
memmove(dst + 0x2c5, "\x4d\x08\xc8\x9d\xc4\x50\x49\x70\x48\x4d\xd0\x12\xd9\x7c\x62\x5e\x6b\xd3\x84\xd5\x36\x42\xfe\x86\x8e\x7a\x23\x59\xa0\x20\xf0\xc5\x02\x20\x5f\x70\x93\x61\x5a\xe4\x20\xcf\xb9\x8a\xf5\xdd\x87\xd0\x48\x6d\x7d\x59\xef\x9e\x0e\x11\xa3\x8e\xf7\xe3\xe2\xf5\x35\x37\x99\x1a", 66);//somu-sig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,369 +0,0 @@
|
|||||||
// Copyright 2019 SoloKeys Developers
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
|
||||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
|
||||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
|
||||||
// copied, modified, or distributed except according to those terms.
|
|
||||||
/*
|
|
||||||
* Wrapper for crypto implementation on device
|
|
||||||
*
|
|
||||||
* */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
#include "crypto.h"
|
|
||||||
|
|
||||||
#ifdef USE_SOFTWARE_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include "sha256.h"
|
|
||||||
#include "uECC.h"
|
|
||||||
#include "aes.h"
|
|
||||||
#include "ctap.h"
|
|
||||||
#include "device.h"
|
|
||||||
// stuff for SHA512
|
|
||||||
#include "sha2.h"
|
|
||||||
#include "blockwise.h"
|
|
||||||
#include APP_CONFIG
|
|
||||||
#include "log.h"
|
|
||||||
#include "memory_layout.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
MBEDTLS_ECP_DP_NONE = 0,
|
|
||||||
MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */
|
|
||||||
MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */
|
|
||||||
MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */
|
|
||||||
MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */
|
|
||||||
MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */
|
|
||||||
MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */
|
|
||||||
MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */
|
|
||||||
MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */
|
|
||||||
MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */
|
|
||||||
MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */
|
|
||||||
MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
|
|
||||||
MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
|
|
||||||
} mbedtls_ecp_group_id;
|
|
||||||
|
|
||||||
|
|
||||||
static SHA256_CTX sha256_ctx;
|
|
||||||
static cf_sha512_context sha512_ctx;
|
|
||||||
static const struct uECC_Curve_t * _es256_curve = NULL;
|
|
||||||
static const uint8_t * _signing_key = NULL;
|
|
||||||
static int _key_len = 0;
|
|
||||||
|
|
||||||
// Secrets for testing only
|
|
||||||
static uint8_t master_secret[64];
|
|
||||||
static uint8_t transport_secret[32];
|
|
||||||
|
|
||||||
|
|
||||||
void crypto_sha256_init(void)
|
|
||||||
{
|
|
||||||
sha256_init(&sha256_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha512_init(void)
|
|
||||||
{
|
|
||||||
cf_sha512_init(&sha512_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_load_master_secret(uint8_t * key)
|
|
||||||
{
|
|
||||||
#if KEY_SPACE_BYTES < 96
|
|
||||||
#error "need more key bytes"
|
|
||||||
#endif
|
|
||||||
memmove(master_secret, key, 64);
|
|
||||||
memmove(transport_secret, key+64, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_reset_master_secret(void)
|
|
||||||
{
|
|
||||||
memset(master_secret, 0, 64);
|
|
||||||
memset(transport_secret, 0, 32);
|
|
||||||
ctap_generate_rng(master_secret, 64);
|
|
||||||
ctap_generate_rng(transport_secret, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void crypto_sha256_update(uint8_t * data, size_t len)
|
|
||||||
{
|
|
||||||
sha256_update(&sha256_ctx, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha512_update(const uint8_t * data, size_t len) {
|
|
||||||
cf_sha512_update(&sha512_ctx, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha256_update_secret()
|
|
||||||
{
|
|
||||||
sha256_update(&sha256_ctx, master_secret, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha256_final(uint8_t * hash)
|
|
||||||
{
|
|
||||||
sha256_final(&sha256_ctx, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha512_final(uint8_t * hash)
|
|
||||||
{
|
|
||||||
// NB: there is also cf_sha512_digest
|
|
||||||
cf_sha512_digest_final(&sha512_ctx, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
|
||||||
{
|
|
||||||
uint8_t buf[64];
|
|
||||||
unsigned int i;
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
|
|
||||||
if (key == CRYPTO_MASTER_KEY)
|
|
||||||
{
|
|
||||||
key = master_secret;
|
|
||||||
klen = sizeof(master_secret)/2;
|
|
||||||
}
|
|
||||||
else if (key == CRYPTO_TRANSPORT_KEY)
|
|
||||||
{
|
|
||||||
key = transport_secret;
|
|
||||||
klen = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(klen > 64)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR, "Error, key size must be <= 64\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memmove(buf, key, klen);
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(buf); i++)
|
|
||||||
{
|
|
||||||
buf[i] = buf[i] ^ 0x36;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sha256_init();
|
|
||||||
crypto_sha256_update(buf, 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
|
||||||
{
|
|
||||||
uint8_t buf[64];
|
|
||||||
unsigned int i;
|
|
||||||
crypto_sha256_final(hmac);
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
if (key == CRYPTO_MASTER_KEY)
|
|
||||||
{
|
|
||||||
key = master_secret;
|
|
||||||
klen = sizeof(master_secret)/2;
|
|
||||||
}
|
|
||||||
else if (key == CRYPTO_TRANSPORT_KEY2)
|
|
||||||
{
|
|
||||||
key = transport_secret;
|
|
||||||
klen = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(klen > 64)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR, "Error, key size must be <= 64\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
memmove(buf, key, klen);
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(buf); i++)
|
|
||||||
{
|
|
||||||
buf[i] = buf[i] ^ 0x5c;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sha256_init();
|
|
||||||
crypto_sha256_update(buf, 64);
|
|
||||||
crypto_sha256_update(hmac, 32);
|
|
||||||
crypto_sha256_final(hmac);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_init(void)
|
|
||||||
{
|
|
||||||
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
|
||||||
_es256_curve = uECC_secp256r1();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_load_attestation_key(void)
|
|
||||||
{
|
|
||||||
// static uint8_t _key [32];
|
|
||||||
flash_attestation_page * page =(flash_attestation_page *)ATTESTATION_PAGE_ADDR;
|
|
||||||
// memmove(_key, (uint8_t *)ATTESTATION_KEY_ADDR, 32);
|
|
||||||
_signing_key = page->attestation_key;
|
|
||||||
_key_len = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
|
|
||||||
{
|
|
||||||
if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR, "error, uECC failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_ecc256_load_key(uint8_t * data, int len, uint8_t * data2, int len2)
|
|
||||||
{
|
|
||||||
static uint8_t privkey[32];
|
|
||||||
generate_private_key(data,len,data2,len2,privkey);
|
|
||||||
_signing_key = privkey;
|
|
||||||
_key_len = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID)
|
|
||||||
{
|
|
||||||
|
|
||||||
const struct uECC_Curve_t * curve = NULL;
|
|
||||||
|
|
||||||
switch(MBEDTLS_ECP_ID)
|
|
||||||
{
|
|
||||||
case MBEDTLS_ECP_DP_SECP192R1:
|
|
||||||
curve = uECC_secp192r1();
|
|
||||||
if (_key_len != 24) goto fail;
|
|
||||||
break;
|
|
||||||
case MBEDTLS_ECP_DP_SECP224R1:
|
|
||||||
curve = uECC_secp224r1();
|
|
||||||
if (_key_len != 28) goto fail;
|
|
||||||
break;
|
|
||||||
case MBEDTLS_ECP_DP_SECP256R1:
|
|
||||||
curve = uECC_secp256r1();
|
|
||||||
if (_key_len != 32) goto fail;
|
|
||||||
break;
|
|
||||||
case MBEDTLS_ECP_DP_SECP256K1:
|
|
||||||
curve = uECC_secp256k1();
|
|
||||||
if (_key_len != 32) goto fail;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf2(TAG_ERR, "error, invalid ECDSA alg specifier\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( uECC_sign(_signing_key, data, len, sig, curve) == 0)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR, "error, uECC failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
printf2(TAG_ERR, "error, invalid key length\n");
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, uint8_t * privkey)
|
|
||||||
{
|
|
||||||
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
|
|
||||||
crypto_sha256_update(data, len);
|
|
||||||
crypto_sha256_update(data2, len2);
|
|
||||||
crypto_sha256_update(master_secret, 32); // TODO AES
|
|
||||||
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
|
|
||||||
|
|
||||||
crypto_aes256_init(master_secret + 32, NULL);
|
|
||||||
crypto_aes256_encrypt(privkey, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);*/
|
|
||||||
void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y)
|
|
||||||
{
|
|
||||||
uint8_t privkey[32];
|
|
||||||
uint8_t pubkey[64];
|
|
||||||
|
|
||||||
generate_private_key(data,len,NULL,0,privkey);
|
|
||||||
|
|
||||||
memset(pubkey,0,sizeof(pubkey));
|
|
||||||
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
|
||||||
memmove(x,pubkey,32);
|
|
||||||
memmove(y,pubkey+32,32);
|
|
||||||
}
|
|
||||||
void crypto_ecc256_compute_public_key(uint8_t * privkey, uint8_t * pubkey)
|
|
||||||
{
|
|
||||||
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void crypto_load_external_key(uint8_t * key, int len)
|
|
||||||
{
|
|
||||||
_signing_key = key;
|
|
||||||
_key_len = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey)
|
|
||||||
{
|
|
||||||
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR, "Error, uECC_make_key failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret)
|
|
||||||
{
|
|
||||||
if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR, "Error, uECC_shared_secret failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AES_ctx aes_ctx;
|
|
||||||
void crypto_aes256_init(uint8_t * key, uint8_t * nonce)
|
|
||||||
{
|
|
||||||
if (key == CRYPTO_TRANSPORT_KEY)
|
|
||||||
{
|
|
||||||
AES_init_ctx(&aes_ctx, transport_secret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AES_init_ctx(&aes_ctx, key);
|
|
||||||
}
|
|
||||||
if (nonce == NULL)
|
|
||||||
{
|
|
||||||
memset(aes_ctx.Iv, 0, 16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memmove(aes_ctx.Iv, nonce, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent round key recomputation
|
|
||||||
void crypto_aes256_reset_iv(uint8_t * nonce)
|
|
||||||
{
|
|
||||||
if (nonce == NULL)
|
|
||||||
{
|
|
||||||
memset(aes_ctx.Iv, 0, 16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memmove(aes_ctx.Iv, nonce, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_aes256_decrypt(uint8_t * buf, int length)
|
|
||||||
{
|
|
||||||
AES_CBC_decrypt_buffer(&aes_ctx, buf, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_aes256_encrypt(uint8_t * buf, int length)
|
|
||||||
{
|
|
||||||
AES_CBC_encrypt_buffer(&aes_ctx, buf, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error "No crypto implementation defined"
|
|
||||||
#endif
|
|
@ -285,7 +285,7 @@ static void device_migrate(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_init(int argc, char *argv[])
|
void device_init()
|
||||||
{
|
{
|
||||||
|
|
||||||
hw_init(LOW_FREQUENCY);
|
hw_init(LOW_FREQUENCY);
|
||||||
@ -468,20 +468,8 @@ void heartbeat(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void authenticator_read_state(AuthenticatorState * a)
|
|
||||||
{
|
|
||||||
uint32_t * ptr = (uint32_t *)flash_addr(STATE1_PAGE);
|
|
||||||
memmove(a,ptr,sizeof(AuthenticatorState));
|
|
||||||
}
|
|
||||||
|
|
||||||
void authenticator_read_backup_state(AuthenticatorState * a)
|
static int authenticator_is_backup_initialized(void)
|
||||||
{
|
|
||||||
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
|
|
||||||
memmove(a,ptr,sizeof(AuthenticatorState));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return 1 yes backup is init'd, else 0
|
|
||||||
int authenticator_is_backup_initialized(void)
|
|
||||||
{
|
{
|
||||||
uint8_t header[16];
|
uint8_t header[16];
|
||||||
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
|
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
|
||||||
@ -490,20 +478,35 @@ int authenticator_is_backup_initialized(void)
|
|||||||
return state->is_initialized == INITIALIZED_MARKER;
|
return state->is_initialized == INITIALIZED_MARKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
void authenticator_write_state(AuthenticatorState * a, int backup)
|
int authenticator_read_state(AuthenticatorState * a)
|
||||||
{
|
{
|
||||||
if (! backup)
|
uint32_t * ptr = (uint32_t *) flash_addr(STATE1_PAGE);
|
||||||
{
|
memmove(a, ptr, sizeof(AuthenticatorState));
|
||||||
flash_erase_page(STATE1_PAGE);
|
|
||||||
|
|
||||||
flash_write(flash_addr(STATE1_PAGE), (uint8_t*)a, sizeof(AuthenticatorState));
|
if (a->is_initialized != INITIALIZED_MARKER){
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flash_erase_page(STATE2_PAGE);
|
|
||||||
|
|
||||||
flash_write(flash_addr(STATE2_PAGE), (uint8_t*)a, sizeof(AuthenticatorState));
|
if (authenticator_is_backup_initialized()){
|
||||||
|
printf1(TAG_ERR,"Warning: memory corruption detected. restoring from backup..\n");
|
||||||
|
ptr = (uint32_t *) flash_addr(STATE2_PAGE);
|
||||||
|
memmove(a, ptr, sizeof(AuthenticatorState));
|
||||||
|
authenticator_write_state(a);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void authenticator_write_state(AuthenticatorState * a)
|
||||||
|
{
|
||||||
|
flash_erase_page(STATE1_PAGE);
|
||||||
|
flash_write(flash_addr(STATE1_PAGE), (uint8_t*)a, sizeof(AuthenticatorState));
|
||||||
|
|
||||||
|
flash_erase_page(STATE2_PAGE);
|
||||||
|
flash_write(flash_addr(STATE2_PAGE), (uint8_t*)a, sizeof(AuthenticatorState));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(IS_BOOTLOADER)
|
#if !defined(IS_BOOTLOADER)
|
||||||
@ -752,11 +755,6 @@ int ctap_generate_rng(uint8_t * dst, size_t num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ctap_user_verification(uint8_t arg)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ctap_reset_rk(void)
|
void ctap_reset_rk(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -861,6 +859,17 @@ void boot_solo_bootloader(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void device_read_aaguid(uint8_t * dst){
|
||||||
|
uint8_t * aaguid = (uint8_t *)"\x88\x76\x63\x1b\xd4\xa0\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79";
|
||||||
|
memmove(dst, aaguid, 16);
|
||||||
|
if (device_is_nfc()){
|
||||||
|
dst[0] = 0x89;
|
||||||
|
}
|
||||||
|
else if (tsc_sensor_exists()){
|
||||||
|
dst[0] = 0x98;
|
||||||
|
}
|
||||||
|
dump_hex1(TAG_GREEN,dst, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _Error_Handler(char *file, int line)
|
void _Error_Handler(char *file, int line)
|
||||||
|
@ -4,105 +4,83 @@
|
|||||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||||
// copied, modified, or distributed except according to those terms.
|
// copied, modified, or distributed except according to those terms.
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <stdlib.h>
|
||||||
#include "stm32l4xx.h"
|
#include <stdint.h>
|
||||||
#include "stm32l4xx_ll_gpio.h"
|
#include <stdbool.h>
|
||||||
#include "stm32l4xx_ll_rcc.h"
|
#include <unistd.h>
|
||||||
#include "stm32l4xx_ll_system.h"
|
|
||||||
#include "stm32l4xx_ll_pwr.h"
|
|
||||||
#include "stm32l4xx_ll_utils.h"
|
|
||||||
#include "stm32l4xx_ll_cortex.h"
|
|
||||||
#include "stm32l4xx_ll_gpio.h"
|
|
||||||
#include "stm32l4xx_ll_usart.h"
|
|
||||||
#include "stm32l4xx_ll_bus.h"
|
|
||||||
#include "stm32l4xx_ll_usb.h"
|
|
||||||
|
|
||||||
#include "stm32l4xx_hal_pcd.h"
|
#include "cbor.h"
|
||||||
|
|
||||||
#include "usbd_core.h"
|
|
||||||
#include "usbd_desc.h"
|
|
||||||
#include "usbd_hid.h"
|
|
||||||
/*#include "usbd_hid.h"*/
|
|
||||||
|
|
||||||
#include APP_CONFIG
|
|
||||||
#include "flash.h"
|
|
||||||
#include "rng.h"
|
|
||||||
#include "led.h"
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#include "ctaphid.h"
|
||||||
|
//#include "bsp.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "fifo.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "ctap.h"
|
||||||
|
#include APP_CONFIG
|
||||||
|
|
||||||
#ifdef TEST_SOLO_STM32
|
#if !defined(TEST)
|
||||||
#define Error_Handler() _Error_Handler(__FILE__,__LINE__)
|
|
||||||
#define PAGE_SIZE 2048
|
|
||||||
#define PAGES 128
|
|
||||||
// Pages 119-127 are data
|
|
||||||
#define COUNTER2_PAGE (PAGES - 4)
|
|
||||||
#define COUNTER1_PAGE (PAGES - 3)
|
|
||||||
#define STATE2_PAGE (PAGES - 2)
|
|
||||||
#define STATE1_PAGE (PAGES - 1)
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t __90_ms = 0;
|
int main(int argc, char *argv[])
|
||||||
#define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN))
|
|
||||||
|
|
||||||
// Timer6 overflow handler. happens every ~90ms.
|
|
||||||
void TIM6_DAC_IRQHandler()
|
|
||||||
{
|
{
|
||||||
// timer is only 16 bits, so roll it over here
|
uint8_t hidmsg[64];
|
||||||
TIM6->SR = 0;
|
uint32_t t1 = 0;
|
||||||
__90_ms += 1;
|
|
||||||
}
|
set_logging_mask(
|
||||||
|
/*0*/
|
||||||
|
//TAG_GEN|
|
||||||
|
// TAG_MC |
|
||||||
|
// TAG_GA |
|
||||||
|
TAG_WALLET |
|
||||||
|
TAG_STOR |
|
||||||
|
//TAG_NFC_APDU |
|
||||||
|
TAG_NFC |
|
||||||
|
//TAG_CP |
|
||||||
|
// TAG_CTAP|
|
||||||
|
//TAG_HID|
|
||||||
|
TAG_U2F|
|
||||||
|
//TAG_PARSE |
|
||||||
|
//TAG_TIME|
|
||||||
|
// TAG_DUMP|
|
||||||
|
TAG_GREEN|
|
||||||
|
TAG_RED|
|
||||||
|
TAG_EXT|
|
||||||
|
TAG_CCID|
|
||||||
|
TAG_ERR
|
||||||
|
);
|
||||||
|
|
||||||
|
device_init(argc, argv);
|
||||||
|
|
||||||
|
memset(hidmsg,0,sizeof(hidmsg));
|
||||||
|
|
||||||
uint32_t millis(void)
|
|
||||||
{
|
|
||||||
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _Error_Handler(char *file, int line)
|
|
||||||
{
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
}
|
if (millis() - t1 > HEARTBEAT_PERIOD)
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
uint32_t i = 5;
|
|
||||||
|
|
||||||
hw_init();
|
|
||||||
|
|
||||||
LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT);
|
|
||||||
LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP);
|
|
||||||
flash_option_bytes_init(1);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
uint32_t t0 = millis() % 750;
|
|
||||||
if (! IS_BUTTON_PRESSED())
|
|
||||||
{
|
{
|
||||||
if (t0 < 750*1/3)
|
heartbeat();
|
||||||
{
|
t1 = millis();
|
||||||
led_rgb(0 | (0 << 8) | (i << 17));
|
}
|
||||||
}
|
|
||||||
else if (t0 < 750*2/3)
|
device_manage();
|
||||||
{
|
|
||||||
led_rgb(0 | (i << 8) | (0 << 16));
|
if (usbhid_recv(hidmsg) > 0)
|
||||||
}
|
{
|
||||||
else
|
ctaphid_handle_packet(hidmsg);
|
||||||
{
|
memset(hidmsg, 0, sizeof(hidmsg));
|
||||||
led_rgb(i | (0 << 8) | (0 << 16));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
led_rgb(0x151515);
|
|
||||||
}
|
}
|
||||||
|
ctaphid_check_timeouts();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should never get here
|
||||||
|
usbhid_close();
|
||||||
|
printf1(TAG_GREEN, "done\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -67,7 +67,7 @@ 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
|
#define ATTESTATION_CONFIGURED_TAG 0xaa551e79
|
||||||
|
|
||||||
struct flash_attestation_page{
|
struct flash_attestation_page{
|
||||||
uint8_t attestation_key[32];
|
uint8_t attestation_key[32];
|
||||||
|
25
targets/stm32l432/src/solo.h
Normal file
25
targets/stm32l432/src/solo.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef _SOLO_H_
|
||||||
|
#define _SOLO_H_
|
||||||
|
|
||||||
|
void device_init();
|
||||||
|
|
||||||
|
void main_loop_delay();
|
||||||
|
void usbhid_init();
|
||||||
|
void usbhid_close();
|
||||||
|
int usbhid_recv(uint8_t * msg);
|
||||||
|
|
||||||
|
void heartbeat();
|
||||||
|
|
||||||
|
// Called each main loop. Doesn't need to do anything.
|
||||||
|
void device_manage();
|
||||||
|
|
||||||
|
void device_init_button();
|
||||||
|
|
||||||
|
// For Solo hacker
|
||||||
|
void boot_solo_bootloader();
|
||||||
|
void boot_st_bootloader();
|
||||||
|
|
||||||
|
|
||||||
|
void delay(uint32_t ms);
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
ecdsa
|
ecdsa
|
||||||
fido2
|
fido2==0.7.3
|
||||||
intelhex
|
intelhex
|
||||||
pyserial
|
pyserial
|
||||||
solo-python
|
solo-python
|
||||||
|
Reference in New Issue
Block a user