Merge branch 'nfc' into nfc2

This commit is contained in:
Oleg Moiseenko 2019-02-07 14:49:47 +02:00 committed by GitHub
commit 32400c8d09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 945 additions and 528 deletions

4
.clabot Normal file
View File

@ -0,0 +1,4 @@
{
"contributors": "https://raw.githubusercontent.com/solokeys/contributors/master/contributors.json",
"message": "We require contributors to sign our Copyright License Agreement, and we don't have {{usersWithoutCLA}} on file. In order for us to review and merge your code, please visit https://solokeys.com/legal/contributors, or contact @nickray, @conorpp or @0x0ece for further information or help."
}

4
.gitmodules vendored
View File

@ -3,7 +3,7 @@
url = https://github.com/intel/tinycbor url = https://github.com/intel/tinycbor
[submodule "python-fido2"] [submodule "python-fido2"]
path = python-fido2 path = python-fido2
url = https://github.com/SoloKeysSec/python-fido2 url = https://github.com/solokeys/python-fido2
[submodule "crypto/micro-ecc"] [submodule "crypto/micro-ecc"]
path = crypto/micro-ecc path = crypto/micro-ecc
url = https://github.com/kmackay/micro-ecc.git url = https://github.com/kmackay/micro-ecc.git
@ -12,4 +12,4 @@
url = https://github.com/kokke/tiny-AES-c url = https://github.com/kokke/tiny-AES-c
[submodule "targets/stm32l442/dfuse-tool"] [submodule "targets/stm32l442/dfuse-tool"]
path = targets/stm32l442/dfuse-tool path = targets/stm32l442/dfuse-tool
url = https://github.com/SoloKeysSec/dfuse-tool url = https://github.com/solokeys/dfuse-tool

View File

@ -1,4 +1,4 @@
dist: trusty dist: xenial
language: c language: c
compiler: gcc compiler: gcc
addons: addons:
@ -7,6 +7,7 @@ addons:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- gcc-7 - gcc-7
- cppcheck
script: script:
- export CC=gcc-7 - export CC=gcc-7
- make test - make test

View File

@ -1,6 +1,17 @@
# Notify ModemManager this device should be ignored
ACTION!="add|change|move", GOTO="mm_usb_device_blacklist_end"
SUBSYSTEM!="usb", GOTO="mm_usb_device_blacklist_end"
ENV{DEVTYPE}!="usb_device", GOTO="mm_usb_device_blacklist_end"
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ENV{ID_MM_DEVICE_IGNORE}="1"
LABEL="mm_usb_device_blacklist_end"
# Solo # Solo
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo", TAG+="uaccess", GROUP="plugdev", SYMLINK+="solokey" ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo", TAG+="uaccess", GROUP="plugdev", SYMLINK+="solokey"
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo HACKER (Unlocked)", TAG+="uaccess", GROUP="plugdev", SYMLINK+="solohacker" ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo HACKER (Unlocked)", TAG+="uaccess", GROUP="plugdev", SYMLINK+="solohacker"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess", GROUP="plugdev", SYMLINK+="solokey-serial"
# U2F Zero # U2F Zero
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess", GROUP="plugdev", SYMLINK+="u2fzero" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess", GROUP="plugdev", SYMLINK+="u2fzero"

View File

@ -45,9 +45,6 @@ cbor: $(LIBCBOR)
$(LIBCBOR): tinycbor/Makefile $(LIBCBOR): tinycbor/Makefile
cd tinycbor/ && $(MAKE) clean && $(MAKE) -j8 cd tinycbor/ && $(MAKE) clean && $(MAKE) -j8
test:
$(MAKE) -C . main
.PHONY: efm8prog .PHONY: efm8prog
efm8prog: efm8prog:
cd './targets/efm8\Keil 8051 v9.53 - Debug' && $(MAKE) all cd './targets/efm8\Keil 8051 v9.53 - Debug' && $(MAKE) all
@ -92,6 +89,16 @@ wink3: env3
fido2-test: env3 fido2-test: env3
env3/bin/python tools/ctap_test.py env3/bin/python tools/ctap_test.py
CPPCHECK_FLAGS=--quiet --error-exitcode=2
cppcheck:
cppcheck $(CPPCHECK_FLAGS) crypto/aes-gcm
cppcheck $(CPPCHECK_FLAGS) crypto/sha256
cppcheck $(CPPCHECK_FLAGS) fido2
cppcheck $(CPPCHECK_FLAGS) pc
test: main cppcheck
clean: clean:
rm -f *.o main.exe main $(obj) rm -f *.o main.exe main $(obj)
rm -rf env2 env3 rm -rf env2 env3

View File

@ -1,8 +1,8 @@
![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg) [![License](https://img.shields.io/github/license/solokeys/solo.svg)](https://github.com/solokeys/solo/blob/master/LICENSE)
[![Kickstarter](https://img.shields.io/badge/kickstarter-back%20us-red.svg)](https://solokeys.com/kickstarter) [![Build Status](https://travis-ci.com/solokeys/solo.svg?branch=master)](https://travis-ci.com/solokeys/solo)
[![Build Status](https://travis-ci.com/SoloKeysSec/solo.svg?branch=master)](https://travis-ci.com/SoloKeysSec/solo) [![Discourse Users](https://img.shields.io/discourse/https/discourse.solokeys.com/users.svg)](https://discourse.solokeys.com)
[![Discourse Status](https://img.shields.io/discourse/https/meta.discourse.org/status.svg)](https://discourse.solokeys.com)
[![Keybase Chat](https://img.shields.io/badge/chat-on%20keybase-brightgreen.svg)](https://keybase.io/team/solokeys.public) [![Keybase Chat](https://img.shields.io/badge/chat-on%20keybase-brightgreen.svg)](https://keybase.io/team/solokeys.public)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo?ref=badge_shield)
# Solo # Solo
@ -35,20 +35,25 @@ Solo for Hacker is a special version of Solo that let you customize its firmware
You can only buy Solo for Hacker at [solokeys.com](https://solokeys.com), as we don't sell it on Amazon and other places to avoid confusing customers. If you buy a Hacker, you can permanently lock it into a regular Solo, but viceversa you can NOT take a regular Solo and turn it a Hacker. You can only buy Solo for Hacker at [solokeys.com](https://solokeys.com), as we don't sell it on Amazon and other places to avoid confusing customers. If you buy a Hacker, you can permanently lock it into a regular Solo, but viceversa you can NOT take a regular Solo and turn it a Hacker.
If you have a Solo for Hacker, here's how you can load your own code on it. You can find more details, including how to permanently lock it, in our [documentation](https://solo.solokeys.io/building/). If you have a Solo for Hacker, here's how you can load your own code on it. You can find more details, including how to permanently lock it, in our [documentation](https://docs.solokeys.io/solo/building/).
```bash ```bash
git clone --recurse-submodules https://github.com/SoloKeysSec/solo git clone --recurse-submodules https://github.com/solokeys/solo
cd solo cd solo
cd targets/stm32l432 cd targets/stm32l432
make cbor make cbor
make all-hacker make all-hacker
python ../../tools/solotool.py program solo.hex cd ../..
make env3
source env3/bin/activate
python tools/solotool.py program targets/stm32l432/solo.hex
``` ```
If you forgot the `--recurse-submodules` when cloning, simply `git submodule update --init --recursive`. If you forgot the `--recurse-submodules` when cloning, simply `git submodule update --init --recursive`.
For example, if you want to turn off any blue light emission, you can edit [`led_rgb()`](https://github.com/SoloKeysSec/solo/blob/master/targets/stm32l432/src/led.c#L15) and force:
For example, if you want to turn off any blue light emission, you can edit [`led_rgb()`](https://github.com/solokeys/solo/blob/master/targets/stm32l432/src/led.c#L15) and force:
``` ```
uint32_t b = 0; uint32_t b = 0;
``` ```
@ -65,7 +70,7 @@ A frequently asked question is whether Solo for Hacker is less secure than regul
Clone Solo and build it Clone Solo and build it
```bash ```bash
git clone --recurse-submodules https://github.com/SoloKeysSec/solo git clone --recurse-submodules https://github.com/solokeys/solo
cd solo cd solo
make all make all
``` ```
@ -93,12 +98,12 @@ Or any client example such as:
python python-fido2/examples/credential.py python python-fido2/examples/credential.py
``` ```
You can find more details in our [documentation](https://solo.solokeys.io), including how to build on the the NUCLEO-L432KC development board. You can find more details in our [documentation](https://docs.solokeys.io/solo/), including how to build on the the NUCLEO-L432KC development board.
# Documentation # Documentation
Check out our [official documentation](https://solo.solokeys.io). Check out our [official documentation](https://docs.solokeys.io/solo/).
# Contributors # Contributors
@ -117,6 +122,9 @@ All software is licensed under GPLv3, and hardware under CC BY-SA 4.0.
Software and hardware are available under licenses for commercial use. Please contact SoloKeys for more information. Software and hardware are available under licenses for commercial use. Please contact SoloKeys for more information.
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo?ref=badge_large)
# Where To Buy Solo # Where To Buy Solo
You can buy Solo, Solo Tap, and Solo for Hackers at [solokeys.com](https://solokeys.com). You can buy Solo, Solo Tap, and Solo for Hackers at [solokeys.com](https://solokeys.com).

View File

@ -1,4 +0,0 @@
Welcome to the technical documentation for [solokeyssec/solo](https://github.com/solokeyssec/solo).
For now, you can read the repository `README.md`, more documentation to come!

View File

@ -1 +0,0 @@
../README.md

View File

@ -68,6 +68,10 @@ reconnect each time you program Solo.
python tools/solotool.py monitor <serial-port> python tools/solotool.py monitor <serial-port>
``` ```
#### Linux Users:
[See issue 62](https://github.com/solokeys/solo/issues/62).
### Building a Solo release ### Building a Solo release
If you want to build a release of Solo, we recommend trying a Hacker build first If you want to build a release of Solo, we recommend trying a Hacker build first

View File

@ -1,15 +1,15 @@
We are very open to contributions! We are very open to contributions!
[Currently](https://github.com/solokeyssec/solo/issues), most work will go towards [Currently](https://github.com/solokeys/solo/issues), most work will go towards
* implementing STM32L432 * ~~implementing STM32L432~~
* implementing NFC * implementing NFC
* adding documentation and improving accessability of the code * adding documentation and improving accessability of the code
In the future, we would love to see creative plugins/extensions, putting the TRNG and other features of the STM32L432 to good use! In the future, we would love to see creative plugins/extensions, putting the TRNG and other features of the STM32L432 to good use!
Feel free to send a [pull request](https://github.com/SoloKeysSec/solo/pulls) at any time, we don't currently have a formal contribution process. Feel free to send a [pull request](https://github.com/solokeys/solo/pulls) at any time, please note that we do require a lightweight copyright license agreement in order to accept contributions. Reason and procedure: <https://solokeys.com/legal/contributors/>.
If you want to discuss your plans in quasi-realtime beforehand, you can also join our [solokeys.public](https://keybase.io/team/solokeys.public) Keybase team. If you want to discuss your plans in quasi-realtime beforehand, you can also join our [solokeys.public](https://keybase.io/team/solokeys.public) Keybase team.
But first: [join our mailing list!](https://solokeys.us19.list-manage.com/subscribe/post?u=cc0c298fb99cd136bdec8294b&id=b9cb3de62d) But first: [join our mailing list!](https://solokeys.us19.list-manage.com/subscribe/post?u=cc0c298fb99cd136bdec8294b&id=6550fc947a)

View File

@ -15,6 +15,8 @@ A master secret, `M`, is generated at initialization. This is only used for
all key generation and derivation in FIDO2. Solo uses a key wrapping method all key generation and derivation in FIDO2. Solo uses a key wrapping method
for FIDO2 operation. for FIDO2 operation.
** NOTE: The masked implementation of AES is planned, but not yet implemented. Currently it is normal AES. **
## Key wrapping ## Key wrapping
When you register a service with a FIDO2 or U2F authenticator, the When you register a service with a FIDO2 or U2F authenticator, the
@ -55,6 +57,8 @@ keys which are then used for FIDO2/U2F. -->
## Key derivation ## Key derivation
** Planned, but not yet implemented. **
Master secret `M` consists of 64 bytes, split into equal parts `M1` and `M2`. Master secret `M` consists of 64 bytes, split into equal parts `M1` and `M2`.
In theory, we should only need 32 bytes to achieve 256 security, but we also In theory, we should only need 32 bytes to achieve 256 security, but we also
plan to have side channel security hence the added bytes. plan to have side channel security hence the added bytes.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

4
docs/solo/index.md Normal file
View File

@ -0,0 +1,4 @@
Welcome to the technical documentation for [solokeys/solo](https://github.com/solokeys/solo).
For now, you can read the repository `README.md`, more documentation to come!

View File

@ -0,0 +1,12 @@
For information on what this is, see the [spec](https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-metadata-statement-v2.0-rd-20180702.html#fido2-example).
## CTAP2
```
{!metadata/solo-FIDO2-CTAP2-Authenticator.json!}
```
## U2F
```
{!metadata/solo-FIDO2-U2F-Authenticator.json!}
```

1
docs/solo/repo-readme.md Symbolic link
View File

@ -0,0 +1 @@
../../README.md

View File

@ -22,5 +22,5 @@ In order to boot the application, a valid signature must be provided to the boot
signature using a public key stored in the bootloader section, and the data in the application section. If the signature signature using a public key stored in the bootloader section, and the data in the application section. If the signature
is valid, the boot flag in the data section will be changed to allow boot. is valid, the boot flag in the data section will be changed to allow boot.
Signature checks and checks to the data section boot flag are made redundantly to make glitching attacks more difficult. Random delays We are working to make the signature checking process redundantly to make glitching attacks more difficult. Also random delays
between redundant checks are also made. between redundant checks.

View File

@ -1,6 +1,6 @@
# tl;dr # tl;dr
Create [`/etc/udev/99-solo.rules`](https://github.com/SoloKeysSec/solo/blob/master/99-solo.rules) and add the following (which assumes your user is in group `plugdev`): Create [`/etc/udev/rules.d/99-solo.rules`](https://github.com/solokeys/solo/blob/master/99-solo.rules) and add the following (which assumes your user is in group `plugdev`):
``` ```
# Solo # Solo
@ -13,7 +13,7 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct
Then run Then run
``` ```
udevadm trigger sudo udevadm control --reload-rules && sudo udevadm trigger
``` ```
# How do udev rules work and why are they needed # How do udev rules work and why are they needed
@ -65,8 +65,8 @@ udevadm trigger
## What about vendor and product ID for Solo? ## What about vendor and product ID for Solo?
| Key | Vendor ID | Product ID | | Key | Vendor ID | Product ID |
| --- | --- | --- | | --- | --- | --- |
| Solo | 10c4 | 8acf | | Solo | 0483 | a2ca |
| U2F Zero | 0483 | a2ca | | U2F Zero | 10c4 | 8acf |
## You got this all wrong, I can't believe it! ## You got this all wrong, I can't believe it!
Are you suffering from [us being wrong](https://xkcd.com/386/)? Please, send us a [pull request](https://github.com/SoloKeysSec/solo/pulls) and prove us wrong :D Are you suffering from [us being wrong](https://xkcd.com/386/)? Please, send us a [pull request](https://github.com/solokeys/solo/pulls) and prove us wrong :D

View File

@ -61,20 +61,20 @@ int main(int argc, char * argv[])
); );
device_init(); device_init();
printf1(TAG_GEN,"init device\n"); // printf1(TAG_GEN,"init device\n");
usbhid_init(); usbhid_init();
printf1(TAG_GEN,"init usb\n"); // printf1(TAG_GEN,"init usb\n");
ctaphid_init(); ctaphid_init();
printf1(TAG_GEN,"init ctaphid\n"); // printf1(TAG_GEN,"init ctaphid\n");
ctap_init(); // ctap_init();
printf1(TAG_GEN,"init ctap\n"); // printf1(TAG_GEN,"init ctap\n");
memset(hidmsg,0,sizeof(hidmsg)); memset(hidmsg,0,sizeof(hidmsg));
printf1(TAG_GEN,"recv'ing hid msg \n"); // printf1(TAG_GEN,"recv'ing hid msg \n");
while(1) while(1)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,27 @@
site_name: Solo site_name: Solo Technical Documentation
site_author: SoloKeys site_author: SoloKeys
site_description: 'Documentation for the SoloKeys solo software' site_description: 'Documentation for the SoloKeys solo software'
repo_url: 'https://github.com/solokeyssec/solo' site_url: 'https://docs.solokeys.io/solo/'
repo_name: 'solokeyssec/solo' repo_url: 'https://github.com/solokeys/solo'
copyright: 'Copyright &copy; 2018 SoloKeys' repo_name: 'solokeys/solo'
copyright: 'Copyright &copy; 2018 - 2019 SoloKeys'
nav: nav:
- Home: index.md - Home: solo/index.md
- README.md: repo-readme.md - FIDO2 Implementation: solo/fido2-impl.md
- FIDO2 Implementation: fido2-impl.md - Metadata Statements: solo/metadata-statements.md
- Signed update process: signed-updates.md - Build instructions: solo/building.md
- Building: building.md - Signed update process: solo/signed-updates.md
- Code documentation: code-overview.md - Code documentation: solo/code-overview.md
- Contributing Code: contributing.md - Contributing Code: solo/contributing.md
- Contributing Docs: documenting.md - Contributing Docs: solo/documenting.md
- What the udev?!: udev.md - udev Rules: solo/udev.md
- About: solo/repo-readme.md
theme: theme:
name: material name: material
logo: 'images/logo.svg' logo: 'solo/images/logo.svg'
favicon: 'solo/images/favicon.ico'
markdown_extensions:
- markdown_include.include

View File

@ -54,7 +54,11 @@ void device_set_status(int status)
int udp_server() int udp_server()
{ {
int fd; static bool run_already = false;
static int fd = -1;
if (run_already && fd >= 0) return fd;
run_already = true;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror( "socket failed" ); perror( "socket failed" );
return 1; return 1;

View File

@ -8,7 +8,7 @@ all:
$(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DFLASH_ROP=1' $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DFLASH_ROP=1'
all-hacker: all-hacker:
$(MAKE) -f application.mk solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
all-locked: all-locked:
$(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) EXTRA_DEFINES='-DFLASH_ROP=2' $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) EXTRA_DEFINES='-DFLASH_ROP=2'
@ -45,7 +45,6 @@ clean2:
$(MAKE) -f application.mk clean $(MAKE) -f application.mk clean
$(MAKE) -f bootloader.mk clean $(MAKE) -f bootloader.mk clean
flash: solo.hex bootloader.hex flash: solo.hex bootloader.hex
$(merge_hex) solo.hex bootloader.hex all.hex $(merge_hex) solo.hex bootloader.hex all.hex
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
@ -56,8 +55,7 @@ flash_dfu: solo.hex bootloader.hex
# STM32_Programmer_CLI -c port=usb1 -halt -e all --readunprotect # STM32_Programmer_CLI -c port=usb1 -halt -e all --readunprotect
STM32_Programmer_CLI -c port=usb1 -halt -rdu -d all.hex STM32_Programmer_CLI -c port=usb1 -halt -rdu -d all.hex
flashboot: solo.hex bootloader.hex flashboot:
$(merge_hex) solo.hex bootloader.hex all.hex
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst

View File

@ -1,4 +1,4 @@
# STM32L4xx Solo # STM32L432 Solo
Check out our [official documentation](https://solo.solokeys.io/building/) Check out our [official documentation](https://docs.solokeys.io/solo/building/)
for instructions on building and programming! for instructions on building and programming!

View File

@ -66,7 +66,7 @@
#define SKIP_BUTTON_CHECK_FAST 1 #define SKIP_BUTTON_CHECK_FAST 1
void printing_init(); void printing_init();
void hw_init(void); void hw_init(int lf);
// Trigger software reset // Trigger software reset
void device_reboot(); void device_reboot();

View File

@ -23,6 +23,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_gpio.h"
#include "stm32l4xx.h"
#include "cbor.h" #include "cbor.h"
#include "device.h" #include "device.h"
#include "ctaphid.h" #include "ctaphid.h"
@ -32,9 +36,8 @@
#include "ctap.h" #include "ctap.h"
#include "app.h" #include "app.h"
#include "memory_layout.h" #include "memory_layout.h"
#include "stm32l4xx_ll_rcc.h" #include "init.h"
#include "stm32l4xx.h"
uint8_t REBOOT_FLAG = 0; uint8_t REBOOT_FLAG = 0;
@ -82,7 +85,16 @@ int main(int argc, char * argv[])
TAG_ERR TAG_ERR
); );
device_init(); // device_init();
init_gpio();
init_millisecond_timer(1);
#if DEBUG_LEVEL > 0
init_debug_uart();
#endif
printf1(TAG_GEN,"init device\n"); printf1(TAG_GEN,"init device\n");
t1 = millis(); t1 = millis();
@ -118,7 +130,14 @@ int main(int argc, char * argv[])
printf1(TAG_RED,"Not authorized to boot (%08x == %08lx)\r\n", AUTH_WORD_ADDR, *(uint32_t*)AUTH_WORD_ADDR); printf1(TAG_RED,"Not authorized to boot (%08x == %08lx)\r\n", AUTH_WORD_ADDR, *(uint32_t*)AUTH_WORD_ADDR);
} }
start_bootloader: start_bootloader:
SystemClock_Config();
init_gpio();
init_millisecond_timer(0);
init_pwm();
init_rng();
usbhid_init(); usbhid_init();
printf1(TAG_GEN,"init usb\n"); printf1(TAG_GEN,"init usb\n");
ctaphid_init(); ctaphid_init();

View File

@ -56,12 +56,14 @@
#ifndef SOLO_HACKER #ifndef SOLO_HACKER
#define USBD_MANUFACTURER_STRING "Solo Keys" #define USBD_MANUFACTURER_STRING "Solo Keys"
#define USBD_PRODUCT_FS_STRING "Solo" #define USBD_PRODUCT_FS_STRING "Solo"
#define USBD_SERIAL_NUM "solocafebabe" #ifndef USBD_SERIAL_NUM
#define USBD_SERIAL_NUM "0123456789ABCDEF"
#endif
#else #else
#define USBD_MANUFACTURER_STRING "Solo Keys" #define USBD_MANUFACTURER_STRING "Solo Keys"
#define USBD_PRODUCT_FS_STRING "Solo HACKER (Unlocked)" #define USBD_PRODUCT_FS_STRING "Solo HACKER (Unlocked)"
#ifndef USBD_SERIAL_NUM #ifndef USBD_SERIAL_NUM
#define USBD_SERIAL_NUM "Solo-Keys-Solo" #define USBD_SERIAL_NUM "0123456789ABCDEF"
#endif #endif
#endif #endif

View File

@ -114,15 +114,10 @@ USBD_ClassTypeDef USBD_HID =
NULL, NULL,
USBD_HID_GetFSCfgDesc,
NULL, USBD_HID_GetFSCfgDesc,
NULL, USBD_HID_GetFSCfgDesc,
NULL, USBD_HID_GetDeviceQualifierDesc,
NULL,
// USBD_HID_GetFSCfgDesc,
// USBD_HID_GetFSCfgDesc,
// USBD_HID_GetFSCfgDesc,
// USBD_HID_GetDeviceQualifierDesc,
}; };
#define USBD_HID_CfgHSDesc USBD_HID_OtherSpeedCfgDesc #define USBD_HID_CfgHSDesc USBD_HID_OtherSpeedCfgDesc

View File

@ -79,27 +79,16 @@ uint8_t ams_read_reg(uint8_t addr)
return data; return data;
} }
// data must be 14 bytes long
void read_reg_block2(AMS_DEVICE * dev)
{
int i;
for (i = 0; i < 0x20; i++)
{
dev->buf[i] = ams_read_reg(i);
}
}
// data must be 14 bytes long // data must be 14 bytes long
void read_reg_block(AMS_DEVICE * dev) void read_reg_block(AMS_DEVICE * dev)
{ {
int i; int i;
uint8_t mode = 0x20 | (0 ); uint8_t mode = 0x20 | (4 );
flush_rx(); flush_rx();
send_recv(mode); send_recv(mode);
for (i = 0; i < 0x20; i++) for (i = 0x04; i < 0x0d; i++)
{ {
dev->buf[i] = send_recv(0); dev->buf[i] = send_recv(0);
} }
@ -204,6 +193,30 @@ const char * ams_get_state_string(uint8_t regval)
return "STATE_WRONG"; return "STATE_WRONG";
} }
int ams_state_is_valid(uint8_t regval)
{
if (regval & AMS_STATE_INVALID)
{
return 0;
}
switch (regval & AMS_STATE_MASK)
{
case AMS_STATE_OFF:
case AMS_STATE_SENSE:
case AMS_STATE_RESOLUTION:
case AMS_STATE_RESOLUTION_L2:
case AMS_STATE_SELECTED:
case AMS_STATE_SECTOR2:
case AMS_STATE_SECTORX_2:
case AMS_STATE_SELECTEDX:
case AMS_STATE_SENSEX_L2:
case AMS_STATE_SENSEX:
case AMS_STATE_SLEEP:
return 1;
}
return 0;
}
void ams_print_int0(uint8_t int0) void ams_print_int0(uint8_t int0)
{ {
uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); uint32_t tag = (TAG_NFC)|(TAG_NO_TAG);
@ -252,6 +265,7 @@ void ams_print_int1(uint8_t int0)
printf1(tag,"\r\n"); printf1(tag,"\r\n");
} }
bool ams_init() bool ams_init()
{ {
@ -265,10 +279,9 @@ bool ams_init()
LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_Enable(SPI1); LL_SPI_Enable(SPI1);
delay(10); // delay(10);
SELECT(); SELECT();
delay(10); // delay(10);
ams_write_command(AMS_CMD_DEFAULT); ams_write_command(AMS_CMD_DEFAULT);
ams_write_command(AMS_CMD_CLEAR_BUFFER); ams_write_command(AMS_CMD_CLEAR_BUFFER);
@ -285,6 +298,10 @@ bool ams_init()
// enable tunneling mode and RF configuration // enable tunneling mode and RF configuration
ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD);
// enable tunneling mode and RF configuration
ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD);
ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block);
printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4);
@ -316,7 +333,7 @@ bool ams_init()
ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block);
printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4);
uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V1;
uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD;
if (block[0] != ic_cfg1 || block[1] != ic_cfg2) if (block[0] != ic_cfg1 || block[1] != ic_cfg2)
@ -342,6 +359,7 @@ bool ams_init()
ams_read_eeprom_block(0x7F, block); ams_read_eeprom_block(0x7F, block);
printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4);
} }
}
return true; return true;
} }

View File

@ -52,6 +52,9 @@ uint8_t ams_read_reg(uint8_t addr);
void ams_write_reg(uint8_t addr, uint8_t tx); void ams_write_reg(uint8_t addr, uint8_t tx);
const char * ams_get_state_string(uint8_t regval);
int ams_state_is_valid(uint8_t regval);
#define AMS_REG_IO_CONF 0x00 #define AMS_REG_IO_CONF 0x00
#define AMS_REG_IC_CONF0 0x01 #define AMS_REG_IC_CONF0 0x01
@ -70,11 +73,21 @@ void ams_write_reg(uint8_t addr, uint8_t tx);
#define AMS_STATE_SELECTED (6 << 3) #define AMS_STATE_SELECTED (6 << 3)
#define AMS_STATE_SECTOR2 (7 << 3) #define AMS_STATE_SECTOR2 (7 << 3)
#define AMS_STATE_SECTORX_2 (0xf << 3) #define AMS_STATE_SECTORX_2 (0xf << 3)
#define AMS_STATE_SELECTEDX (0xd << 3) #define AMS_STATE_SELECTEDX (0xe << 3)
#define AMS_STATE_SENSEX_L2 (0xa << 3) #define AMS_STATE_SENSEX_L2 (0xa << 3)
#define AMS_STATE_SENSEX (0xb << 3) #define AMS_STATE_SENSEX (0xb << 3)
#define AMS_STATE_SLEEP (0x9 << 3) #define AMS_STATE_SLEEP (0x9 << 3)
// ... // // ... //
#define AMS_REG_MASK_INT0 0x08
#define AMS_MASK0_PU (1<<7) // power up
#define AMS_MASK0_WU_A (1<<6) // selected INT
#define AMS_MASK0_SLP (1<<5)
#define AMS_MASK0_EEW_RF (1<<4)
#define AMS_MASK0_EER_RF (1<<3)
#define AMS_MASK0_RXE (1<<2)
#define AMS_MASK0_TXE (1<<1)
#define AMS_MASK0_XRF (1<<0)
#define AMS_REG_MASK_INT1 0x09
#define AMS_REG_INT0 0x0a #define AMS_REG_INT0 0x0a
#define AMS_INT_XRF (1<<0) #define AMS_INT_XRF (1<<0)
#define AMS_INT_TXE (1<<1) #define AMS_INT_TXE (1<<1)
@ -109,6 +122,11 @@ void ams_write_reg(uint8_t addr, uint8_t tx);
#define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2) #define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2) #define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V1 (0x02<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V2 (0x03<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V3 (0x04<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V4 (0x05<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V5 (0x06<<2)
#define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00 #define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00
#define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01 #define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01

View File

@ -45,7 +45,7 @@
#define DISABLE_CTAPHID_CBOR #define DISABLE_CTAPHID_CBOR
void printing_init(); void printing_init();
void hw_init(void); void hw_init(int lf);
//#define TEST //#define TEST
//#define TEST_POWER //#define TEST_POWER
@ -73,6 +73,9 @@ void hw_init(void);
#define SOLO_AMS_CS_PORT GPIOB #define SOLO_AMS_CS_PORT GPIOB
#define SOLO_AMS_CS_PIN LL_GPIO_PIN_0 #define SOLO_AMS_CS_PIN LL_GPIO_PIN_0
#define SOLO_AMS_IRQ_PORT GPIOC
#define SOLO_AMS_IRQ_PIN LL_GPIO_PIN_15
#define SKIP_BUTTON_CHECK_WITH_DELAY 0 #define SKIP_BUTTON_CHECK_WITH_DELAY 0
#define SKIP_BUTTON_CHECK_FAST 0 #define SKIP_BUTTON_CHECK_FAST 0

View File

@ -43,12 +43,17 @@
#include "stm32l4xx_ll_iwdg.h" #include "stm32l4xx_ll_iwdg.h"
#include "usbd_cdc_if.h" #include "usbd_cdc_if.h"
#include "nfc.h" #include "nfc.h"
#include "init.h"
#define LOW_FREQUENCY 1
#define HIGH_FREQUENCY 0
uint32_t __90_ms = 0; uint32_t __90_ms = 0;
uint32_t __device_status = 0; uint32_t __device_status = 0;
uint32_t __last_update = 0; uint32_t __last_update = 0;
extern PCD_HandleTypeDef hpcd; extern PCD_HandleTypeDef hpcd;
bool haveNFC = false; bool haveNFC = false;
bool isLowFreq = 0;
#define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN))
@ -112,12 +117,15 @@ void device_reboot()
{ {
NVIC_SystemReset(); NVIC_SystemReset();
} }
void device_init() void device_init()
{ {
hw_init();
LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT); // hw_init(LOW_FREQUENCY);
LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); // isLowFreq = 1;
hw_init(HIGH_FREQUENCY);
isLowFreq = 0;
#ifndef IS_BOOTLOADER #ifndef IS_BOOTLOADER
#if BOOT_TO_DFU #if BOOT_TO_DFU
@ -127,38 +135,46 @@ void device_init()
#endif #endif
printf1(TAG_GEN,"init nfc\n"); printf1(TAG_GEN,"init nfc\n");
haveNFC = nfc_init(); haveNFC = nfc_init();
if (haveNFC) // if (haveNFC)
printf1(TAG_GEN,"NFC OK.\n"); // printf1(TAG_GEN,"NFC OK.\n");
else // else
printf1(TAG_GEN,"NFC not found.\n"); // printf1(TAG_GEN,"NFC not found.\n");
#endif #endif
printf1(TAG_GEN,"hello solo\r\n"); // printf1(TAG_GEN,"hello solo\r\n");
}
void wait_for_usb_tether()
{
while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) )
;
while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) )
;
delay(10);
while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) )
;
} }
void usb_init(void);
void usbhid_init() void usbhid_init()
{ {
usb_init(); if (!isLowFreq)
{
init_usb();
#if DEBUG_LEVEL>1 #if DEBUG_LEVEL>1
wait_for_usb_tether(); wait_for_usb_tether();
#endif #endif
}
else
{
}
} }
void wait_for_usb_tether()
{
while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) )
;
while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) )
;
delay(10);
while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) )
;
}
int usbhid_recv(uint8_t * msg) int usbhid_recv(uint8_t * msg)
{ {
if (fifo_hidmsg_size()) if (fifo_hidmsg_size())

View File

@ -45,57 +45,53 @@
#include "usbd_composite.h" #include "usbd_composite.h"
#include "usbd_cdc_if.h" #include "usbd_cdc_if.h"
#include "device.h" #include "device.h"
#include "init.h"
#include APP_CONFIG #include APP_CONFIG
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
USBD_HandleTypeDef Solo_USBD_Device; USBD_HandleTypeDef Solo_USBD_Device;
/* Private function prototypes -----------------------------------------------*/
static void LL_Init(void); static void LL_Init(void);
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_TIM2_Init(void);
static void MX_TIM6_Init(void);
static void MX_RNG_Init(void);
static void MX_SPI1_Init(void);
#define Error_Handler() _Error_Handler(__FILE__,__LINE__) #define Error_Handler() _Error_Handler(__FILE__,__LINE__)
void _Error_Handler(char *file, int line); void _Error_Handler(char *file, int line);
void hw_init(void) void hw_init(int lowfreq)
{ {
#ifdef IS_BOOTLOADER #ifdef IS_BOOTLOADER
SCB->VTOR = FLASH_BASE; SCB->VTOR = FLASH_BASE;
#else #else
#endif #endif
LL_Init(); LL_Init();
init_gpio();
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); if (lowfreq)
{
SystemClock_Config_LF();
}
else
{
SystemClock_Config();
}
SystemClock_Config(); // TODO bootloader should not change clk freq.
MX_GPIO_Init();
MX_TIM2_Init(); // PWM for LEDs
MX_TIM6_Init(); // ~1 ms timer if (!lowfreq)
{
init_pwm();
}
init_millisecond_timer(lowfreq);
#if DEBUG_LEVEL > 0 #if DEBUG_LEVEL > 0
MX_USART1_UART_Init();// debug uart init_debug_uart();
#endif #endif
MX_RNG_Init(); init_rng();
MX_SPI1_Init(); init_spi();
TIM6->SR = 0;
__enable_irq();
NVIC_EnableIRQ(TIM6_IRQn);
} }
static void LL_Init(void) static void LL_Init(void)
@ -122,15 +118,14 @@ static void LL_Init(void)
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
} }
static int NFC = 0;
/** /**
* @brief System Clock Configuration * @brief System Clock Configuration
* @retval None * @retval None
*/ */
void SystemClock_Config(void) void SystemClock_Config(void)
{ {
if (!NFC) SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
{
LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
@ -210,9 +205,12 @@ void SystemClock_Config(void)
/* SysTick_IRQn interrupt configuration */ /* SysTick_IRQn interrupt configuration */
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
} }
else
{ void SystemClock_Config_LF4(void)
{
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
@ -266,21 +264,142 @@ void SystemClock_Config(void)
/* SysTick_IRQn interrupt configuration */ /* SysTick_IRQn interrupt configuration */
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
}
} }
void usb_init() // 8MHz
void SystemClock_Config_LF(void)
{ {
if (!NFC) SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
{ {
Error_Handler();
}
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
LL_RCC_LSI_Enable();
/* Wait till LSI is ready */
// while(LL_RCC_LSI_IsReady() != 1)
// {
//
// }
LL_RCC_MSI_Enable();
/* Wait till MSI is ready */
// while(LL_RCC_MSI_IsReady() != 1)
// {
//
// }
LL_RCC_MSI_EnableRangeSelection();
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_7);
LL_RCC_MSI_SetCalibTrimming(0);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI);
/* Wait till System clock is ready */
// while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI)
// {
//
// }
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_Init1msTick(8000000);
LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
LL_SetSystemCoreClock(8000000);
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI);
/* SysTick_IRQn interrupt configuration */
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
}
// 16MHz
void SystemClock_Config_LF16(void)
{
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
{
Error_Handler();
}
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
LL_RCC_LSI_Enable();
/* Wait till LSI is ready */
while(LL_RCC_LSI_IsReady() != 1)
{
}
LL_RCC_MSI_Enable();
/* Wait till MSI is ready */
while(LL_RCC_MSI_IsReady() != 1)
{
}
LL_RCC_MSI_EnableRangeSelection();
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_8);
LL_RCC_MSI_SetCalibTrimming(0);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI);
/* Wait till System clock is ready */
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI)
{
}
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_Init1msTick(16000000);
LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
LL_SetSystemCoreClock(16000000);
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI);
/* SysTick_IRQn interrupt configuration */
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
}
void init_usb()
{
// enable USB power // enable USB power
SET_BIT(PWR->CR2, PWR_CR2_USV); SET_BIT(PWR->CR2, PWR_CR2_USV);
// Enable USB Clock // Enable USB Clock
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN);
#if DEBUG_LEVEL > 0
USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC); USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC);
in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0; in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0;
out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0; out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0;
@ -294,16 +413,17 @@ void usb_init()
// //
// USBD_RegisterClass(&Solo_USBD_Device, &USBD_CDC); // USBD_RegisterClass(&Solo_USBD_Device, &USBD_CDC);
USBD_CDC_RegisterInterface(&Solo_USBD_Device, &USBD_Interface_fops_FS); USBD_CDC_RegisterInterface(&Solo_USBD_Device, &USBD_Interface_fops_FS);
#else
USBD_Init(&Solo_USBD_Device, &Solo_Desc, 0);
USBD_RegisterClass(&Solo_USBD_Device, &USBD_HID);
#endif
USBD_Start(&Solo_USBD_Device); USBD_Start(&Solo_USBD_Device);
}
} }
/* TIM2 init function */ void init_pwm(void)
static void MX_TIM2_Init(void)
{ {
// if(!NFC)
{
LL_TIM_InitTypeDef TIM_InitStruct; LL_TIM_InitTypeDef TIM_InitStruct;
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; LL_TIM_OC_InitTypeDef TIM_OC_InitStruct;
@ -369,12 +489,10 @@ static void MX_TIM2_Init(void)
LL_GPIO_Init(GPIOA, &GPIO_InitStruct); LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
LL_TIM_EnableCounter(TIM2); LL_TIM_EnableCounter(TIM2);
}
} }
/* USART1 init function */ void init_debug_uart(void)
static void MX_USART1_UART_Init(void)
{ {
LL_USART_InitTypeDef USART_InitStruct; LL_USART_InitTypeDef USART_InitStruct;
@ -411,20 +529,35 @@ static void MX_USART1_UART_Init(void)
} }
/** Pinout Configuration void init_gpio(void)
*/
static void MX_GPIO_Init(void)
{ {
/* GPIO Ports Clock Enable */ /* GPIO Ports Clock Enable */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
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);
#ifdef SOLO_AMS_IRQ_PORT
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
/**/
LL_GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = SOLO_AMS_IRQ_PIN;
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(SOLO_AMS_IRQ_PORT, &GPIO_InitStruct);
LL_GPIO_SetPinMode(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_MODE_INPUT);
LL_GPIO_SetPinPull(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_PULL_UP);
#endif
} }
void init_millisecond_timer(int lf)
/* TIM6 init function */
static void MX_TIM6_Init(void)
{ {
LL_TIM_InitTypeDef TIM_InitStruct; LL_TIM_InitTypeDef TIM_InitStruct;
@ -434,10 +567,10 @@ static void MX_TIM6_Init(void)
// 48 MHz sys clock --> 6 MHz timer clock // 48 MHz sys clock --> 6 MHz timer clock
// 48 MHz / 48000 == 1000 Hz // 48 MHz / 48000 == 1000 Hz
if (!NFC) if (!lf)
TIM_InitStruct.Prescaler = 48000; TIM_InitStruct.Prescaler = 48000;
else else
TIM_InitStruct.Prescaler = 4000; TIM_InitStruct.Prescaler = 8000;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 90; TIM_InitStruct.Autoreload = 90;
@ -454,39 +587,14 @@ static void MX_TIM6_Init(void)
// Start immediately // Start immediately
LL_TIM_EnableCounter(TIM6); LL_TIM_EnableCounter(TIM6);
TIM6->SR = 0;
__enable_irq();
NVIC_EnableIRQ(TIM6_IRQn);
} }
/* TIM7 init function */
// static void MX_TIM7_Init(void)
// {
//
// LL_TIM_InitTypeDef TIM_InitStruct;
//
// /* Peripheral clock enable */
// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7);
//
// // 48 MHz sys clock --> 6 MHz timer clock
// // 6 MHz / 6000 == 1000 Hz
// TIM_InitStruct.Prescaler = 48000;
// TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
// TIM_InitStruct.Autoreload = 0xffff;
// LL_TIM_Init(TIM6, &TIM_InitStruct);
//
// LL_TIM_DisableARRPreload(TIM7);
//
// LL_TIM_SetTriggerOutput(TIM7, LL_TIM_TRGO_RESET);
//
// LL_TIM_DisableMasterSlaveMode(TIM7);
//
// // enable interrupt
// TIM7->DIER |= 1;
//
// // Start immediately
// LL_TIM_EnableCounter(TIM7);
// }
/* RNG init function */ void init_rng(void)
static void MX_RNG_Init(void)
{ {
/* Peripheral clock enable */ /* Peripheral clock enable */
@ -497,7 +605,7 @@ static void MX_RNG_Init(void)
} }
/* SPI1 init function */ /* SPI1 init function */
static void MX_SPI1_Init(void) void init_spi(void)
{ {
LL_SPI_InitTypeDef SPI_InitStruct; LL_SPI_InitTypeDef SPI_InitStruct;
@ -527,9 +635,6 @@ static void MX_SPI1_Init(void)
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
// if (!NFC)
// SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64;
// else
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
@ -538,7 +643,5 @@ static void MX_SPI1_Init(void)
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA); LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
// LL_SPI_EnableNSSPulseMgt(SPI1);
} }

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2018 SoloKeys, Inc. <https://solokeys.com/>
*
* This file is part of Solo.
*
* Solo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Solo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Solo. If not, see <https://www.gnu.org/licenses/>
*
* This code is available under licenses for commercial use.
* Please contact SoloKeys for more information.
*/
#ifndef _INIT_H_
#define _INIT_H_
void SystemClock_Config(void);
void SystemClock_Config_LF(void);
void init_usb();
void init_gpio(void);
void init_debug_uart(void);
void init_pwm(void);
void init_millisecond_timer(int lf);
void init_rng(void);
void init_spi(void);
#endif

View File

@ -11,10 +11,9 @@
#include "ctap_errors.h" #include "ctap_errors.h"
#define IS_IRQ_ACTIVE() (1 == (LL_GPIO_ReadInputPort(SOLO_AMS_IRQ_PORT) & SOLO_AMS_IRQ_PIN))
// Capability container // Capability container
const CAPABILITY_CONTAINER NFC_CC = { const CAPABILITY_CONTAINER NFC_CC = {
.cclen_hi = 0x00, .cclen_lo = 0x0f, .cclen_hi = 0x00, .cclen_lo = 0x0f,
.version = 0x20, .version = 0x20,
@ -26,8 +25,20 @@ const CAPABILITY_CONTAINER NFC_CC = {
0x00,0x00 } 0x00,0x00 }
}; };
// 13 chars
uint8_t NDEF_SAMPLE[] = "\x00\x14\xd1\x01\x0eU\x04solokeys.com/"; uint8_t NDEF_SAMPLE[] = "\x00\x14\xd1\x01\x0eU\x04solokeys.com/";
// Poor way to get some info while in passive operation
#include <stdarg.h>
void nprintf(const char *format, ...)
{
memmove((char*)NDEF_SAMPLE + sizeof(NDEF_SAMPLE) - 1 - 13," ", 13);
va_list args;
va_start (args, format);
vsnprintf ((char*)NDEF_SAMPLE + sizeof(NDEF_SAMPLE) - 1 - 13, 13, format, args);
va_end (args);
}
static struct static struct
{ {
uint8_t max_frame_size; uint8_t max_frame_size;
@ -231,7 +242,6 @@ void WTX_clear()
bool WTX_on(int WTX_time) bool WTX_on(int WTX_time)
{ {
WTX_clear(); WTX_clear();
WTX_timer = millis(); WTX_timer = millis();
return true; return true;
@ -336,8 +346,11 @@ int answer_rats(uint8_t parameter)
// historical bytes // historical bytes
memcpy(&res[3], (uint8_t *)"SoloKey tap", 11); memcpy(&res[3], (uint8_t *)"SoloKey tap", 11);
nfc_write_frame(res, sizeof(res)); nfc_write_frame(res, sizeof(res));
ams_wait_for_tx(10); ams_wait_for_tx(10);
return 0; return 0;
} }
@ -518,7 +531,7 @@ void nfc_process_iblock(uint8_t * buf, int len)
if (!WTX_off()) if (!WTX_off())
return; return;
printf1(TAG_NFC, "CTAP resp: 0x%02õ len: %d\r\n", status, ctap_resp.length); printf1(TAG_NFC, "CTAP resp: 0x%02<EFBFBD> len: %d\r\n", status, ctap_resp.length);
if (status == CTAP1_ERR_SUCCESS) if (status == CTAP1_ERR_SUCCESS)
{ {
@ -680,40 +693,41 @@ void nfc_process_block(uint8_t * buf, int len)
void nfc_loop() void nfc_loop()
{ {
static uint32_t t1 = 0; static uint32_t t1 = 0;
static uint32_t t2 = 0;
uint8_t buf[32]; uint8_t buf[32];
AMS_DEVICE ams; AMS_DEVICE ams;
int len = 0; int len = 0;
// uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00";
// if (millis() - t1 > interval)
if (1) if (1)
{ {
t1 = millis();
read_reg_block(&ams); read_reg_block(&ams);
uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status;
process_int0(ams.regs.int0); if (state != AMS_STATE_SELECTED && state != AMS_STATE_SELECTEDX)
{
// delay(1); // sleep ?
return;
}
// if (memcmp(def,ams.buf,sizeof(AMS_DEVICE)) != 0)
// {
// printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE));
// }
if (ams.regs.rfid_status) if (ams.regs.rfid_status)
{ {
// uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status;
// if (state != AMS_STATE_SENSE) // if (state != AMS_STATE_SENSE)
// printf1(TAG_NFC," %s %d\r\n", ams_get_state_string(ams.regs.rfid_status), millis()); // printf1(TAG_NFC," %s x%02x\r\n", ams_get_state_string(ams.regs.rfid_status), state);
} }
if (ams.regs.int0 & AMS_INT_INIT) if (ams.regs.int0 & AMS_INT_INIT)
{ {
// Initialize chip!
nfc_state_init(); nfc_state_init();
t1 = millis();
} }
if (ams.regs.int1) if (ams.regs.int1)
{ {
// ams_print_int1(ams.regs.int1); // ams_print_int1(ams.regs.int1);
} }
if (ams.regs.buffer_status2 && (ams.regs.int0 & AMS_INT_RXE))
if ((ams.regs.int0 & AMS_INT_RXE))
{
if (ams.regs.buffer_status2)
{ {
if (ams.regs.buffer_status2 & AMS_BUF_INVALID) if (ams.regs.buffer_status2 & AMS_BUF_INVALID)
{ {
@ -725,6 +739,7 @@ void nfc_loop()
ams_read_buffer(buf, len); ams_read_buffer(buf, len);
} }
} }
}
if (len) if (len)
{ {
@ -742,9 +757,14 @@ void nfc_loop()
printf1(TAG_NFC, "HLTA/Halt\r\n"); printf1(TAG_NFC, "HLTA/Halt\r\n");
break; break;
case NFC_CMD_RATS: case NFC_CMD_RATS:
printf1(TAG_NFC,"RATS\r\n"); t2 = millis();
t1 = millis();
answer_rats(buf[1]); answer_rats(buf[1]);
nprintf("R:%d",t2-t1);
///
LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_12);
///
NFC_STATE.block_num = 1; NFC_STATE.block_num = 1;
clear_ibuf(); clear_ibuf();
WTX_clear(); WTX_clear();
@ -759,10 +779,8 @@ void nfc_loop()
break; break;
} }
}
} }
}
} }

View File

@ -37,7 +37,6 @@ void _putchar(char c)
LL_USART_TransmitData8(DEBUG_UART,c); LL_USART_TransmitData8(DEBUG_UART,c);
#endif #endif
} }
static int NFC = 0;
int _write (int fd, const void *buf, long int len) int _write (int fd, const void *buf, long int len)
@ -53,13 +52,10 @@ int _write (int fd, const void *buf, long int len)
memcpy(&logbuf[logbuflen], data, len); memcpy(&logbuf[logbuflen], data, len);
logbuflen += len; logbuflen += len;
if (!NFC)
{
// Send out USB serial // Send out USB serial
uint8_t res = CDC_Transmit_FS(logbuf, logbuflen); uint8_t res = CDC_Transmit_FS(logbuf, logbuflen);
if (res == USBD_OK) if (res == USBD_OK)
logbuflen = 0; logbuflen = 0;
}
// Send out UART serial // Send out UART serial
while(len--) while(len--)

View File

@ -79,6 +79,8 @@ Reset_Handler:
ldr sp, =_estack /* Atollic update: set stack pointer */ ldr sp, =_estack /* Atollic update: set stack pointer */
/* Copy the data segment initializers from flash to SRAM */ /* Copy the data segment initializers from flash to SRAM */
/* Call the clock system intitialization function.*/
bl SystemInit
movs r1, #0 movs r1, #0
b LoopCopyDataInit b LoopCopyDataInit
@ -106,8 +108,7 @@ LoopFillZerobss:
cmp r2, r3 cmp r2, r3
bcc FillZerobss bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */ /* Call static constructors */
bl __libc_init_array bl __libc_init_array
/* Call the application's entry point.*/ /* Call the application's entry point.*/

View File

@ -106,6 +106,7 @@
*/ */
#include "stm32l4xx.h" #include "stm32l4xx.h"
#include "init.h"
#if !defined (HSE_VALUE) #if !defined (HSE_VALUE)
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
@ -219,6 +220,8 @@ void SystemInit(void)
/* Disable all interrupts */ /* Disable all interrupts */
RCC->CIER = 0x00000000U; RCC->CIER = 0x00000000U;
SystemClock_Config_LF();
} }
/** /**

View File

@ -31,11 +31,17 @@ import tempfile
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from hashlib import sha256 from hashlib import sha256
from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from fido2.hid import CtapHidDevice, CTAPHID from fido2.hid import CtapHidDevice, CTAPHID
from fido2.client import Fido2Client, ClientError from fido2.client import Fido2Client, ClientError
from fido2.ctap import CtapError from fido2.ctap import CtapError
from fido2.ctap1 import CTAP1, ApduError from fido2.ctap1 import CTAP1, ApduError
from fido2.ctap2 import CTAP2
from fido2.utils import Timeout from fido2.utils import Timeout
from fido2.attestation import Attestation
import usb.core import usb.core
import usb.util import usb.util
@ -119,6 +125,7 @@ class SoloBootloader:
class SoloClient: class SoloClient:
def __init__(self,): def __init__(self,):
self.origin = 'https://example.org' self.origin = 'https://example.org'
self.host = 'example.org'
self.exchange = self.exchange_hid self.exchange = self.exchange_hid
self.do_reboot = True self.do_reboot = True
@ -145,6 +152,8 @@ class SoloClient:
raise RuntimeError('No FIDO device found') raise RuntimeError('No FIDO device found')
self.dev = dev self.dev = dev
self.ctap1 = CTAP1(dev) self.ctap1 = CTAP1(dev)
self.ctap2 = CTAP2(dev)
self.client = Fido2Client(dev, self.origin)
if self.exchange == self.exchange_hid: if self.exchange == self.exchange_hid:
self.send_data_hid(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11') self.send_data_hid(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11')
@ -222,6 +231,32 @@ class SoloClient:
def wink(self,): def wink(self,):
self.send_data_hid(CTAPHID.WINK, b'') self.send_data_hid(CTAPHID.WINK, b'')
def reset(self,):
self.ctap2.reset()
def make_credential(self,):
rp = {'id': self.host, 'name': 'example site'}
user = {'id': b'abcdef', 'name': 'example user'}
challenge = 'Y2hhbGxlbmdl'
attest, data = self.client.make_credential(
rp, user, challenge, exclude_list=[]
)
try:
attest.verify(data.hash)
except AttributeError:
verifier = Attestation.for_type(attest.fmt)
verifier().verify(
attest.att_statement,
attest.auth_data,
data.hash
)
print('Register valid')
x5c = attest.att_statement['x5c'][0]
cert = x509.load_der_x509_certificate(x5c, default_backend())
return cert
def enter_solo_bootloader(self,): def enter_solo_bootloader(self,):
""" """
If solo is configured as solo hacker or something similar, If solo is configured as solo hacker or something similar,
@ -560,11 +595,16 @@ def solo_main():
help='Continuously dump random numbers generated from Solo.', help='Continuously dump random numbers generated from Solo.',
) )
parser.add_argument("--wink", action="store_true", help='HID Wink command.') parser.add_argument("--wink", action="store_true", help='HID Wink command.')
parser.add_argument("--reset", action="store_true", help='Issue a FIDO2 reset command. Warning: your credentials will be lost.')
parser.add_argument("--verify-solo", action="store_true", help='Verify that the Solo firmware is from SoloKeys.')
args = parser.parse_args() args = parser.parse_args()
p = SoloClient() p = SoloClient()
p.find_device() p.find_device()
if args.reset:
p.reset()
if args.rng: if args.rng:
while True: while True:
r = p.get_rng(255) r = p.get_rng(255)
@ -575,6 +615,15 @@ def solo_main():
p.wink() p.wink()
sys.exit(0) sys.exit(0)
if args.verify_solo:
cert = p.make_credential()
solo_fingerprint = b'r\xd5\x831&\xac\xfc\xe9\xa8\xe8&`\x18\xe6AI4\xc8\xbeJ\xb8h_\x91\xb0\x99!\x13\xbb\xd42\x95'
if (cert.fingerprint(hashes.SHA256()) == solo_fingerprint):
print('Valid firmware from SoloKeys')
else:
print('This is either a Solo Hacker or a invalid Solo.')
def asked_for_help(): def asked_for_help():
for i, v in enumerate(sys.argv): for i, v in enumerate(sys.argv):
@ -954,6 +1003,10 @@ def main_mergehex():
if __name__ == '__main__': if __name__ == '__main__':
if sys.version_info[0] < 3:
print('Sorry, python3 is required.')
sys.exit(1)
if len(sys.argv) < 2 or (len(sys.argv) == 2 and asked_for_help()): if len(sys.argv) < 2 or (len(sys.argv) == 2 and asked_for_help()):
print('Diverse command line tool for working with Solo') print('Diverse command line tool for working with Solo')
print('usage: %s <command> [options] [-h]' % sys.argv[0]) print('usage: %s <command> [options] [-h]' % sys.argv[0])