Compare commits

..

1 Commits
2.0.0 ... 1.1.0

Author SHA1 Message Date
6a92423f25 Create CHANGELOG.md 2019-02-17 16:16:29 -05:00
59 changed files with 1510 additions and 5691 deletions

10
.gitignore vendored
View File

@ -81,5 +81,15 @@ env3/
.tags* .tags*
targets/*/docs/ targets/*/docs/
main main
targets/efm32/.project
targets/efm32/.settings/com.silabs.ss.framework.ide.project.sls.core.prefs
targets/efm32/.settings/org.eclipse.cdt.codan.core.prefs
targets/efm32/CMSIS/EFM32PG1B/startup_gcc_efm32pg1b.s
targets/efm32/CMSIS/EFM32PG1B/system_efm32pg1b.c
targets/efm32/EFM32.hwconf
targets/efm32/EFM32_EFM32JG1B200F128GM32.hwconf
targets/efm32/emlib/em_adc.c
targets/efm32/emlib/em_assert.c
targets/efm32/emlib/em_cmu.c
builds/* builds/*

6
.gitmodules vendored
View File

@ -1,6 +1,9 @@
[submodule "tinycbor"] [submodule "tinycbor"]
path = tinycbor path = tinycbor
url = https://github.com/intel/tinycbor url = https://github.com/intel/tinycbor
[submodule "python-fido2"]
path = 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
@ -10,6 +13,3 @@
[submodule "targets/stm32l442/dfuse-tool"] [submodule "targets/stm32l442/dfuse-tool"]
path = targets/stm32l442/dfuse-tool path = targets/stm32l442/dfuse-tool
url = https://github.com/solokeys/dfuse-tool url = https://github.com/solokeys/dfuse-tool
[submodule "crypto/cifra"]
path = crypto/cifra
url = https://github.com/solokeys/cifra.git

View File

@ -1 +0,0 @@
udev/70-solokeys-access.rules

28
99-solo.rules Normal file
View File

@ -0,0 +1,28 @@
# 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
## bootloader + firmware access
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess", GROUP="plugdev"
## DFU access
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", TAG+="uaccess", GROUP="plugdev"
## Solo Secure symlink
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo [1-9]*", SYMLINK+="solokey"
## Solo Hacker symlink
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo Hacker [1-9]*", SYMLINK+="solohacker"
## Solo Serial access + symlink
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess", GROUP="plugdev", SYMLINK+="soloserial"
# U2F Zero
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess", GROUP="plugdev", SYMLINK+="u2fzero"

View File

@ -14,7 +14,7 @@ RUN echo "fb31fbdfe08406ece43eef5df623c0b2deb8b53e405e2c878300f7a1f303ee52 gcc.
RUN sha256sum -c gcc.sha256 RUN sha256sum -c gcc.sha256
RUN tar -C /opt -xf gcc.tar.bz2 RUN tar -C /opt -xf gcc.tar.bz2
# 2. Python3.7: for solo-python (merging etc.) # 2. Python3.7: for solotool (merging etc.)
RUN wget -q -O miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh RUN wget -q -O miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh
# from website # from website
RUN echo "866ae9dff53ad0874e1d1a60b1ad1ef8 miniconda.sh" > miniconda.md5 RUN echo "866ae9dff53ad0874e1d1a60b1ad1ef8 miniconda.sh" > miniconda.md5
@ -24,10 +24,8 @@ RUN echo "e5e5b4cd2a918e0e96b395534222773f7241dc59d776db1b9f7fedfcb489157a mini
RUN sha256sum -c miniconda.sha256 RUN sha256sum -c miniconda.sha256
RUN bash ./miniconda.sh -b -p /opt/conda RUN bash ./miniconda.sh -b -p /opt/conda
RUN ln -s /opt/conda/bin/python /usr/local/bin/python3 RUN ln -s /opt/conda/bin/python3 /usr/local/bin/python3
RUN ln -s /opt/conda/bin/python /usr/local/bin/python RUN ln -s /opt/conda/bin/python3 /usr/local/bin/python
RUN ln -s /opt/conda/bin/pip /usr/local/bin/pip3
RUN ln -s /opt/conda/bin/pip /usr/local/bin/pip
# 3. Source code # 3. Source code
RUN git clone --recurse-submodules https://github.com/solokeys/solo /solo --config core.autocrlf=input RUN git clone --recurse-submodules https://github.com/solokeys/solo /solo --config core.autocrlf=input

View File

@ -23,7 +23,6 @@ LDFLAGS += $(LIBCBOR)
CFLAGS = -O2 -fdata-sections -ffunction-sections CFLAGS = -O2 -fdata-sections -ffunction-sections
INCLUDES = -I./tinycbor/src -I./crypto/sha256 -I./crypto/micro-ecc/ -Icrypto/tiny-AES-c/ -I./fido2/ -I./pc -I./fido2/extensions 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 # for crypto/tiny-AES-c
@ -62,7 +61,6 @@ crypto/micro-ecc/uECC.o: ./crypto/micro-ecc/uECC.c
venv: venv:
python3 -m venv venv python3 -m venv venv
venv/bin/pip -q install --upgrade pip
venv/bin/pip -q install --upgrade -r tools/requirements.txt venv/bin/pip -q install --upgrade -r tools/requirements.txt
venv/bin/pip -q install --upgrade black venv/bin/pip -q install --upgrade black
@ -71,7 +69,7 @@ black: venv
venv/bin/black --skip-string-normalization --check tools/ venv/bin/black --skip-string-normalization --check tools/
wink: venv wink: venv
venv/bin/solo key wink venv/bin/python tools/solotool.py solo --wink
fido2-test: venv fido2-test: venv
venv/bin/python tools/ctap_test.py venv/bin/python tools/ctap_test.py
@ -82,7 +80,7 @@ docker-build:
docker build -t $(DOCKER_IMAGE) . docker build -t $(DOCKER_IMAGE) .
docker run --rm -v "$(CURDIR)/builds:/builds" \ docker run --rm -v "$(CURDIR)/builds:/builds" \
-v "$(CURDIR)/in-docker-build.sh:/in-docker-build.sh" \ -v "$(CURDIR)/in-docker-build.sh:/in-docker-build.sh" \
$(DOCKER_IMAGE) "./in-docker-build.sh" $(SOLO_VERSIONISH) $(DOCKER_IMAGE) /in-docker-build.sh $(SOLO_VERSIONISH)
CPPCHECK_FLAGS=--quiet --error-exitcode=2 CPPCHECK_FLAGS=--quiet --error-exitcode=2

View File

@ -48,8 +48,7 @@ cd ../..
make venv make venv
source venv/bin/activate source venv/bin/activate
solo program aux enter-bootloader python tools/solotool.py program targets/stm32l432/solo.hex
solo program bootloader targets/stm32l432/solo.hex
``` ```
Alternatively, run `make docker-build` and use the firmware generated in `/tmp`. Alternatively, run `make docker-build` and use the firmware generated in `/tmp`.

View File

@ -1 +0,0 @@
1.1.1

Submodule crypto/cifra deleted from d04dd31860

View File

@ -55,11 +55,11 @@ If you use `DEBUG=2`, that means Solo will not boot until something starts readi
it's debug messages. So it basically it waits to tether to a serial terminal so that you don't it's debug messages. So it basically it waits to tether to a serial terminal so that you don't
miss any debug messages. miss any debug messages.
We recommend using our `solo` tool as a serial emulator since it will automatically We recommend using our `solotool.py` as a serial emulator since it will automatically
reconnect each time you program Solo. reconnect each time you program Solo.
``` ```
solo monitor <serial-port> python tools/solotool.py monitor <serial-port>
``` ```
#### Linux Users: #### Linux Users:
@ -86,7 +86,7 @@ Programming `all.hex` will cause the device to permanently lock itself.
It's recommended to test a debug/hacker build first to make sure Solo is working as expected. It's recommended to test a debug/hacker build first to make sure Solo is working as expected.
Then you can switch to a locked down build, which cannot be reprogrammed as easily (or not at all!). Then you can switch to a locked down build, which cannot be reprogrammed as easily (or not at all!).
We recommend using our `solo` tool to manage programming. It is cross platform. First you must We recommend using our `solotool.py` to manage programming. It is cross platform. First you must
install the prerequisites: install the prerequisites:
``` ```
@ -101,8 +101,7 @@ If your Solo device is already programmed (it flashes green when powered), we re
programming it using the Solo bootloader. programming it using the Solo bootloader.
``` ```
solo program aux enter-bootloader python tools/solotool.py program solo.hex
solo program bootloader solo.hex
``` ```
Make sure to program `solo.hex` and not `all.hex`. Nothing bad would happen, but you'd Make sure to program `solo.hex` and not `all.hex`. Nothing bad would happen, but you'd
@ -126,10 +125,7 @@ off and it enumerates as "STM BOOTLOADER".
You can program it by running the following. You can program it by running the following.
``` ```
solo program aux enter-bootloader python tools/solotool.py program all.hex --use-dfu --detach
solo program aux enter-dfu
# powercycle key
solo program dfu all.hex
``` ```
Make sure to program `all.hex`, as this contains both the bootloader and the Solo application. Make sure to program `all.hex`, as this contains both the bootloader and the Solo application.
@ -149,14 +145,14 @@ A locked Solo will only accept signed updates.
If this is not a device with a hacker build, you can only program signed updates. If this is not a device with a hacker build, you can only program signed updates.
``` ```
solo program bootloader /path/to/firmware.json python tools/solotool.py program /path/to/firmware.json
``` ```
If you've provisioned the Solo bootloader with your own secp256r1 public key, you can sign your If you've provisioned the Solo bootloader with your own secp256r1 public key, you can sign your
firmware by running the following command. firmware by running the following command.
``` ```
solo sign /path/to/signing-key.pem /path/to/solo.hex /output-path/to/firmware.json python tools/solotool.py sign /path/to/signing-key.pem /path/to/solo.hex /output-path/to/firmware.json
``` ```
If your Solo isn't locked, you can always reprogram it using a debugger connected directly If your Solo isn't locked, you can always reprogram it using a debugger connected directly
@ -179,5 +175,5 @@ If you'd like to also permanently disable signed updates, plug in your programme
``` ```
# WARNING: No more signed updates. # WARNING: No more signed updates.
solo program disable-bootloader python tools/programmer.py --disable
``` ```

View File

@ -1,16 +1,13 @@
# tl;dr # tl;dr
Create a file like [`/etc/udev/rules.d/99-solo.rules`](https://github.com/solokeys/solo/blob/master/99-solo.rules), for instance the following rules should cover access in all cases: 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 bootloader + firmware # Solo
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess", GROUP="plugdev", SYMLINK+="solokey"
# ST DFU bootloader
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", TAG+="uaccess", GROUP="plugdev"
# U2F Zero # U2F Zero
ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess", GROUP="plugdev", SYMLINK+="u2fzero"
``` ```
Then run Then run
@ -53,7 +50,7 @@ This contains rules for Yubico's keys, the U2F Zero, and many others. The releva
``` ```
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess"
``` ```
It matches on the correct vendor/product IDs of 10c4/8acf, and adds the TAG `uaccess`. Older versions of udev use rules such as It matches on the correct vendor/product IDs of 10c4/8acf, and adds the TAG `uaccess`. Older versions of udev use rules such as
``` ```
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", MODE="0644", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", MODE="0644", GROUP="plugdev"
``` ```

View File

@ -1,30 +0,0 @@
#ifndef _APDU_H_
#define _APDU_H_
#include <stdint.h>
typedef struct
{
uint8_t cla;
uint8_t ins;
uint8_t p1;
uint8_t p2;
uint8_t lc;
} __attribute__((packed)) APDU_HEADER;
#define APDU_FIDO_U2F_REGISTER 0x01
#define APDU_FIDO_U2F_AUTHENTICATE 0x02
#define APDU_FIDO_U2F_VERSION 0x03
#define APDU_FIDO_NFCCTAP_MSG 0x10
#define APDU_INS_SELECT 0xA4
#define APDU_INS_READ_BINARY 0xB0
#define SW_SUCCESS 0x9000
#define SW_GET_RESPONSE 0x6100 // Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE.
#define SW_WRONG_LENGTH 0x6700
#define SW_COND_USE_NOT_SATISFIED 0x6985
#define SW_FILE_NOT_FOUND 0x6a82
#define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid
#define SW_INTERNAL_EXCEPTION 0x6f00
#endif //_APDU_H_

View File

@ -60,7 +60,7 @@ 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[32];
static uint8_t transport_secret[32]; static uint8_t transport_secret[32];
@ -73,17 +73,13 @@ void crypto_sha256_init()
void crypto_reset_master_secret() void crypto_reset_master_secret()
{ {
ctap_generate_rng(master_secret, 64); ctap_generate_rng(master_secret, 32);
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 memmove(master_secret, key, 32);
#error "need more key bytes" memmove(transport_secret, key+32, 32);
#endif
memmove(master_secret, key, 64);
memmove(transport_secret, key+64, 32);
} }
void crypto_sha256_update(uint8_t * data, size_t len) void crypto_sha256_update(uint8_t * data, size_t len)
@ -112,12 +108,7 @@ void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
key = master_secret; key = master_secret;
klen = sizeof(master_secret); klen = sizeof(master_secret);
} }
else if (key == CRYPTO_TRANSPORT_KEY)
{
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");

View File

@ -19,10 +19,6 @@ void crypto_sha256_final(uint8_t * 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);
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);
void crypto_sha512_init();
void crypto_sha512_update(const uint8_t * data, size_t len);
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);

View File

@ -25,6 +25,7 @@
#include "device.h" #include "device.h"
#define PIN_TOKEN_SIZE 16
uint8_t PIN_TOKEN[PIN_TOKEN_SIZE]; uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
uint8_t KEY_AGREEMENT_PUB[64]; uint8_t KEY_AGREEMENT_PUB[64];
static uint8_t KEY_AGREEMENT_PRIV[32]; static uint8_t KEY_AGREEMENT_PRIV[32];
@ -33,9 +34,6 @@ static int8_t PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
AuthenticatorState STATE; AuthenticatorState STATE;
static void ctap_reset_key_agreement();
static struct { static struct {
CTAP_authDataHeader authData; CTAP_authDataHeader authData;
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE]; uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
@ -338,12 +336,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
count = auth_data_update_count(&authData->head); count = auth_data_update_count(&authData->head);
device_set_status(CTAPHID_STATUS_UPNEEDED); device_set_status(CTAPHID_STATUS_UPNEEDED);
// if NFC - not need to click a button int but = ctap_user_presence_test();
int but = 1;
if(!device_is_nfc())
{
but = ctap_user_presence_test();
}
if (!but) if (!but)
{ {
@ -565,7 +558,6 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
uint8_t * sigder = auth_data_buf + 32 + 64; uint8_t * sigder = auth_data_buf + 32 + 64;
ret = ctap_parse_make_credential(&MC,encoder,request,length); ret = ctap_parse_make_credential(&MC,encoder,request,length);
if (ret != 0) if (ret != 0)
{ {
printf2(TAG_ERR,"error, parse_make_credential failed\n"); printf2(TAG_ERR,"error, parse_make_credential failed\n");
@ -620,7 +612,6 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
check_ret(ret); check_ret(ret);
} }
CborEncoder map; CborEncoder map;
ret = cbor_encoder_create_map(encoder, &map, 3); ret = cbor_encoder_create_map(encoder, &map, 3);
check_ret(ret); check_ret(ret);
@ -633,6 +624,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
crypto_ecc256_load_attestation_key(); crypto_ecc256_load_attestation_key();
int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder); int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder);
printf1(TAG_MC,"der sig [%d]: ", sigder_sz); dump_hex1(TAG_MC, sigder, sigder_sz); printf1(TAG_MC,"der sig [%d]: ", sigder_sz); dump_hex1(TAG_MC, sigder, sigder_sz);
ret = ctap_add_attest_statement(&map, sigder, sigder_sz); ret = ctap_add_attest_statement(&map, sigder, sigder_sz);
@ -823,7 +815,7 @@ int ctap_filter_invalid_credentials(CTAP_getAssertion * GA)
printf1(TAG_GA, "RK %d is a rpId match!\r\n", i); printf1(TAG_GA, "RK %d is a rpId match!\r\n", i);
if (count == ALLOW_LIST_MAX_SIZE-1) if (count == ALLOW_LIST_MAX_SIZE-1)
{ {
printf2(TAG_ERR, "not enough ram allocated for matching RK's (%d). Skipping.\r\n", count); printf2(TAG_ERR, "not enough ram allocated for matching RK's (%d)\r\n", count);
break; break;
} }
GA->creds[count].type = PUB_KEY_CRED_PUB_KEY; GA->creds[count].type = PUB_KEY_CRED_PUB_KEY;
@ -1190,7 +1182,7 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
crypto_aes256_decrypt(pinHashEnc, 16); crypto_aes256_decrypt(pinHashEnc, 16);
if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0) if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0)
{ {
ctap_reset_key_agreement(); crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
ctap_decrement_pin_attempts(); ctap_decrement_pin_attempts();
if (ctap_device_boot_locked()) if (ctap_device_boot_locked())
{ {
@ -1233,7 +1225,7 @@ uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubke
printf2(TAG_ERR,"platform-pubkey: "); dump_hex1(TAG_ERR, platform_pubkey, 64); printf2(TAG_ERR,"platform-pubkey: "); dump_hex1(TAG_ERR, platform_pubkey, 64);
printf2(TAG_ERR,"device-pubkey: "); dump_hex1(TAG_ERR, KEY_AGREEMENT_PUB, 64); printf2(TAG_ERR,"device-pubkey: "); dump_hex1(TAG_ERR, KEY_AGREEMENT_PUB, 64);
// Generate new keyAgreement pair // Generate new keyAgreement pair
ctap_reset_key_agreement(); crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
ctap_decrement_pin_attempts(); ctap_decrement_pin_attempts();
if (ctap_device_boot_locked()) if (ctap_device_boot_locked())
{ {
@ -1258,7 +1250,6 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
uint8_t pinTokenEnc[PIN_TOKEN_SIZE]; uint8_t pinTokenEnc[PIN_TOKEN_SIZE];
int ret = ctap_parse_client_pin(&CP,request,length); int ret = ctap_parse_client_pin(&CP,request,length);
switch(CP.subCommand) switch(CP.subCommand)
{ {
case CP_cmdSetPin: case CP_cmdSetPin:
@ -1406,7 +1397,6 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
pkt_raw++; pkt_raw++;
length--; length--;
uint8_t * buf = resp->data; uint8_t * buf = resp->data;
cbor_encoder_init(&encoder, buf, resp->data_size, 0); cbor_encoder_init(&encoder, buf, resp->data_size, 0);
@ -1596,16 +1586,12 @@ void ctap_init()
exit(1); exit(1);
} }
if (! device_is_nfc()) crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
{
ctap_reset_key_agreement();
}
#ifdef BRIDGE_TO_WALLET #ifdef BRIDGE_TO_WALLET
wallet_init(); wallet_init();
#endif #endif
} }
uint8_t ctap_is_pin_set() uint8_t ctap_is_pin_set()
@ -1796,10 +1782,7 @@ int8_t ctap_load_key(uint8_t index, uint8_t * key)
return 0; return 0;
} }
static void ctap_reset_key_agreement()
{
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
}
void ctap_reset() void ctap_reset()
{ {
@ -1816,7 +1799,7 @@ void ctap_reset()
ctap_reset_state(); ctap_reset_state();
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH)); memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
ctap_reset_key_agreement(); crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
crypto_reset_master_secret(); crypto_reset_master_secret();
} }

View File

@ -521,7 +521,7 @@ uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up)
if (cbor_value_get_type(&map) != CborBooleanType) if (cbor_value_get_type(&map) != CborBooleanType)
{ {
printf2(TAG_ERR,"Error, expecting bool type for option map value\n"); printf2(TAG_ERR,"Error, expecting text string type for rp map value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE; return CTAP2_ERR_INVALID_CBOR_TYPE;
} }

View File

@ -16,12 +16,6 @@
#include "util.h" #include "util.h"
#include "log.h" #include "log.h"
#include "extensions.h" #include "extensions.h"
// move custom SHA512 command out,
// and the following headers too
#include "sha2.h"
#include "crypto.h"
#include APP_CONFIG #include APP_CONFIG
typedef enum typedef enum
@ -534,10 +528,6 @@ static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * ci
return buffer_status(); return buffer_status();
} }
extern void _check_ret(CborError ret, int line, const char * filename);
#define check_hardcore(r) _check_ret(r,__LINE__, __FILE__);\
if ((r) != CborNoError) exit(1);
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
{ {
uint8_t cmd; uint8_t cmd;
@ -728,155 +718,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
ctaphid_write(&wb, NULL, 0); ctaphid_write(&wb, NULL, 0);
is_busy = 0; is_busy = 0;
break; break;
#endif
#if defined(SOLO_HACKER) && (DEBUG_LEVEL > 0) && (!IS_BOOTLOADER == 1)
case CTAPHID_PROBE:
/*
* Expects CBOR-serialized data of the form
* {"subcommand": "hash_type", "data": b"the_data"}
* with hash_type in SHA256, SHA512
*/
// some random logging
printf1(TAG_HID,"CTAPHID_PROBE\n");
// initialise CTAP response object
ctap_response_init(&ctap_resp);
// initialise write buffer
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_PROBE;
// prepare parsing (or halt)
int ret;
CborParser parser;
CborValue it, map;
ret = cbor_parser_init(
ctap_buffer, (size_t) buffer_len(),
// strictly speaking, CTAP is not RFC canonical...
CborValidateCanonicalFormat,
&parser, &it);
check_hardcore(ret);
CborType type = cbor_value_get_type(&it);
if (type != CborMapType) exit(1);
ret = cbor_value_enter_container(&it,&map);
check_hardcore(ret);
size_t map_length = 0;
ret = cbor_value_get_map_length(&it, &map_length);
if (map_length != 2) exit(1);
// parse subcommand (or halt)
CborValue val;
ret = cbor_value_map_find_value(&it, "subcommand", &val);
check_hardcore(ret);
if (!cbor_value_is_text_string(&val))
exit(1);
int sha_version = 0;
bool found = false;
if (!found) {
ret = cbor_value_text_string_equals(
&val, "SHA256", &found);
check_hardcore(ret);
if (found)
sha_version = 256;
}
if (!found) {
ret = cbor_value_text_string_equals(
&val, "SHA512", &found);
check_hardcore(ret);
if (found)
sha_version = 512;
}
if (sha_version == 0)
exit(1);
// parse data (or halt)
ret = cbor_value_map_find_value(&it, "data", &val);
check_hardcore(ret);
if (!cbor_value_is_byte_string(&val))
exit(1);
size_t data_length = 0;
ret = cbor_value_calculate_string_length(&val, &data_length);
check_hardcore(ret);
if (data_length > 6*1024)
exit(1);
unsigned char data[6*1024];
ret = cbor_value_copy_byte_string (
&val, &data[0], &data_length, &val);
check_hardcore(ret);
// execute subcommand
if (sha_version == 256) {
// calculate hash
crypto_sha256_init();
crypto_sha256_update(data, data_length);
crypto_sha256_final(ctap_buffer);
// write output
wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes
ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ);
}
if (sha_version == 512) {
// calculate hash
crypto_sha512_init();
crypto_sha512_update(data, data_length);
crypto_sha512_final(ctap_buffer);
// write output
wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes
ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ);
}
// finalize
ctaphid_write(&wb, NULL, 0);
is_busy = 0;
break;
/*
case CTAPHID_SHA256:
// some random logging
printf1(TAG_HID,"CTAPHID_SHA256\n");
// initialise CTAP response object
ctap_response_init(&ctap_resp);
// initialise write buffer
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_SHA256;
wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes
// calculate hash
crypto_sha256_init();
crypto_sha256_update(ctap_buffer, buffer_len());
crypto_sha256_final(ctap_buffer);
// copy to output
ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ);
ctaphid_write(&wb, NULL, 0);
is_busy = 0;
break;
case CTAPHID_SHA512:
// some random logging
printf1(TAG_HID,"CTAPHID_SHA512\n");
// initialise CTAP response object
ctap_response_init(&ctap_resp);
// initialise write buffer
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_SHA512;
wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes
// calculate hash
crypto_sha512_init();
crypto_sha512_update(ctap_buffer, buffer_len());
crypto_sha512_final(ctap_buffer);
// copy to output
ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ);
ctaphid_write(&wb, NULL, 0);
is_busy = 0;
break;
*/
#endif #endif
default: default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());

View File

@ -28,8 +28,6 @@
#define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51) #define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51)
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52) #define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
#define CTAPHID_GETRNG (TYPE_INIT | 0x60) #define CTAPHID_GETRNG (TYPE_INIT | 0x60)
// reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0
#define CTAPHID_PROBE (TYPE_INIT | 0x70)
#define ERR_INVALID_CMD 0x01 #define ERR_INVALID_CMD 0x01
#define ERR_INVALID_PAR 0x02 #define ERR_INVALID_PAR 0x02

View File

@ -86,22 +86,5 @@ void boot_st_bootloader();
// HID wink command // HID wink command
void device_wink(); void device_wink();
typedef enum {
DEVICE_LOW_POWER_IDLE = 0,
DEVICE_LOW_POWER_FAST = 1,
DEVICE_FAST = 2,
} DEVICE_CLOCK_RATE;
// Set the clock rate for the device.
// Three modes are targetted for Solo.
// 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.
void device_set_clock_rate(DEVICE_CLOCK_RATE param);
// Returns 1 if operating in NFC mode.
// 0 otherwise.
bool device_is_nfc();
#endif #endif

View File

@ -91,10 +91,10 @@ int16_t extend_fido2(CredentialId * credid, uint8_t * output)
} }
} }
int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len) int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
{ {
struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) payload; struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) req->payload;
uint16_t rcode; uint16_t rcode;
if (req->ins == U2F_AUTHENTICATE) if (req->ins == U2F_AUTHENTICATE)
@ -118,7 +118,7 @@ int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len)
{ {
if ( ! is_extension_request((uint8_t *) &auth->kh, auth->khl)) // Pin requests if ( ! is_extension_request((uint8_t *) &auth->kh, auth->khl)) // Pin requests
{ {
rcode = U2F_SW_WRONG_DATA; rcode = U2F_SW_WRONG_PAYLOAD;
printf1(TAG_EXT, "Ignoring U2F auth request\n"); printf1(TAG_EXT, "Ignoring U2F auth request\n");
dump_hex1(TAG_EXT, (uint8_t *) &auth->kh, auth->khl); dump_hex1(TAG_EXT, (uint8_t *) &auth->kh, auth->khl);
goto end; goto end;

View File

@ -7,9 +7,8 @@
#ifndef EXTENSIONS_H_ #ifndef EXTENSIONS_H_
#define EXTENSIONS_H_ #define EXTENSIONS_H_
#include "u2f.h" #include "u2f.h"
#include "apdu.h"
int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len); int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len);
int16_t extend_fido2(CredentialId * credid, uint8_t * output); int16_t extend_fido2(CredentialId * credid, uint8_t * output);

View File

@ -48,8 +48,6 @@ struct logtag tagtable[] = {
{TAG_STOR,"STOR"}, {TAG_STOR,"STOR"},
{TAG_BOOT,"BOOT"}, {TAG_BOOT,"BOOT"},
{TAG_EXT,"EXT"}, {TAG_EXT,"EXT"},
{TAG_NFC,"NFC"},
{TAG_NFC_APDU, "NAPDU"},
}; };
@ -70,7 +68,7 @@ void LOG(uint32_t tag, const char * filename, int num, const char * fmt, ...)
{ {
if (tag & tagtable[i].tagn) if (tag & tagtable[i].tagn)
{ {
if (tagtable[i].tag[0] && !(tag & TAG_NO_TAG)) printf("[%s] ", tagtable[i].tag); if (tagtable[i].tag[0]) printf("[%s] ", tagtable[i].tag);
i = 0; i = 0;
break; break;
} }

View File

@ -23,30 +23,27 @@ void set_logging_tag(uint32_t tag);
typedef enum typedef enum
{ {
TAG_GEN = (1 << 0), TAG_GEN = (1 << 0),
TAG_MC = (1 << 1), TAG_MC = (1 << 1),
TAG_GA = (1 << 2), TAG_GA = (1 << 2),
TAG_CP = (1 << 3), TAG_CP = (1 << 3),
TAG_ERR = (1 << 4), TAG_ERR = (1 << 4),
TAG_PARSE = (1 << 5), TAG_PARSE= (1 << 5),
TAG_CTAP = (1 << 6), TAG_CTAP = (1 << 6),
TAG_U2F = (1 << 7), TAG_U2F = (1 << 7),
TAG_DUMP = (1 << 8), TAG_DUMP = (1 << 8),
TAG_GREEN = (1 << 9), TAG_GREEN = (1 << 9),
TAG_RED = (1 << 10), TAG_RED= (1 << 10),
TAG_TIME = (1 << 11), TAG_TIME= (1 << 11),
TAG_HID = (1 << 12), TAG_HID = (1 << 12),
TAG_USB = (1 << 13), TAG_USB = (1 << 13),
TAG_WALLET = (1 << 14), TAG_WALLET = (1 << 14),
TAG_STOR = (1 << 15), TAG_STOR = (1 << 15),
TAG_DUMP2 = (1 << 16), TAG_DUMP2 = (1 << 16),
TAG_BOOT = (1 << 17), TAG_BOOT = (1 << 17),
TAG_EXT = (1 << 18), TAG_EXT = (1 << 18),
TAG_NFC = (1 << 19),
TAG_NFC_APDU = (1 << 20),
TAG_NO_TAG = (1UL << 30), TAG_FILENO = (1u << 31)
TAG_FILENO = (1UL << 31)
} LOG_TAG; } LOG_TAG;
#if DEBUG_LEVEL > 0 #if DEBUG_LEVEL > 0

View File

@ -25,33 +25,40 @@ int main()
uint32_t t1 = 0; uint32_t t1 = 0;
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_CP |
TAG_NFC | // TAG_CTAP|
//TAG_CP | // TAG_HID|
//TAG_CTAP| /*TAG_U2F|*/
//TAG_HID| // TAG_PARSE |
//TAG_U2F| // TAG_TIME|
//TAG_PARSE | // TAG_DUMP|
//TAG_TIME| TAG_GREEN|
//TAG_DUMP| TAG_RED|
TAG_GREEN| TAG_ERR
TAG_RED| );
TAG_ERR
);
device_init(); device_init();
printf1(TAG_GEN,"init device\n");
usbhid_init();
printf1(TAG_GEN,"init usb\n");
ctaphid_init();
printf1(TAG_GEN,"init ctaphid\n");
ctap_init();
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)
@ -73,7 +80,6 @@ int main()
{ {
} }
ctaphid_check_timeouts(); ctaphid_check_timeouts();
} }
// Should never get here // Should never get here

View File

@ -10,7 +10,6 @@
#include "crypto.h" #include "crypto.h"
#include "log.h" #include "log.h"
#include "device.h" #include "device.h"
#include "apdu.h"
#include "wallet.h" #include "wallet.h"
#ifdef ENABLE_U2F_EXTENSIONS #ifdef ENABLE_U2F_EXTENSIONS
#include "extensions.h" #include "extensions.h"
@ -28,12 +27,12 @@ void u2f_reset_response();
static CTAP_RESPONSE * _u2f_resp = NULL; static CTAP_RESPONSE * _u2f_resp = NULL;
void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPONSE * resp) void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
{ {
uint16_t rcode = 0; uint16_t rcode = 0;
uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16));
uint8_t byte; uint8_t byte;
ctap_response_init(resp);
u2f_set_writeback_buffer(resp); u2f_set_writeback_buffer(resp);
if (req->cla != 0) if (req->cla != 0)
@ -43,7 +42,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO
goto end; goto end;
} }
#ifdef ENABLE_U2F_EXTENSIONS #ifdef ENABLE_U2F_EXTENSIONS
rcode = extend_u2f(req, payload, len); rcode = extend_u2f(req, len);
#endif #endif
if (rcode != U2F_SW_NO_ERROR && rcode != U2F_SW_CONDITIONS_NOT_SATISFIED) // If the extension didn't do anything... if (rcode != U2F_SW_NO_ERROR && rcode != U2F_SW_CONDITIONS_NOT_SATISFIED) // If the extension didn't do anything...
{ {
@ -60,7 +59,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO
{ {
timestamp(); timestamp();
rcode = u2f_register((struct u2f_register_request*)payload); rcode = u2f_register((struct u2f_register_request*)req->payload);
printf1(TAG_TIME,"u2f_register time: %d ms\n", timestamp()); printf1(TAG_TIME,"u2f_register time: %d ms\n", timestamp());
} }
@ -68,7 +67,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO
case U2F_AUTHENTICATE: case U2F_AUTHENTICATE:
printf1(TAG_U2F, "U2F_AUTHENTICATE\n"); printf1(TAG_U2F, "U2F_AUTHENTICATE\n");
timestamp(); timestamp();
rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1); rcode = u2f_authenticate((struct u2f_authenticate_request*)req->payload, req->p1);
printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", timestamp()); printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", timestamp());
break; break;
case U2F_VERSION: case U2F_VERSION:
@ -110,22 +109,6 @@ end:
printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length); printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length);
} }
void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp)
{
if (len < 5 || !req)
return;
uint32_t alen = req[4];
u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp);
}
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
{
uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16));
u2f_request_ex((APDU_HEADER *)req, req->payload, len, resp);
}
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len) int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len)
{ {
@ -173,7 +156,7 @@ static void u2f_make_auth_tag(struct u2f_key_handle * kh, uint8_t * appid, uint8
memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE); memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE);
} }
int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey) static int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey)
{ {
ctap_generate_rng(kh->key, U2F_KEY_HANDLE_KEY_SIZE); ctap_generate_rng(kh->key, U2F_KEY_HANDLE_KEY_SIZE);
u2f_make_auth_tag(kh, appid, kh->tag); u2f_make_auth_tag(kh, appid, kh->tag);
@ -213,7 +196,6 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
if (control == U2F_AUTHENTICATE_CHECK) if (control == U2F_AUTHENTICATE_CHECK)
{ {
printf1(TAG_U2F, "CHECK-ONLY\r\n");
if (u2f_appid_eq(&req->kh, req->app) == 0) if (u2f_appid_eq(&req->kh, req->app) == 0)
{ {
return U2F_SW_CONDITIONS_NOT_SATISFIED; return U2F_SW_CONDITIONS_NOT_SATISFIED;
@ -224,47 +206,42 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
} }
} }
if ( if (
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) || control != U2F_AUTHENTICATE_SIGN ||
req->khl != U2F_KEY_HANDLE_SIZE || req->khl != U2F_KEY_HANDLE_SIZE ||
u2f_appid_eq(&req->kh, req->app) != 0 || // Order of checks is important u2f_appid_eq(&req->kh, req->app) != 0 || // Order of checks is important
u2f_load_key(&req->kh, req->app) != 0 u2f_load_key(&req->kh, req->app) != 0
) )
{ {
return U2F_SW_WRONG_DATA; return U2F_SW_WRONG_PAYLOAD;
} }
// dont-enforce-user-presence-and-sign
if (control == U2F_AUTHENTICATE_SIGN_NO_USER)
up = 0;
if(!device_is_nfc() && up)
{ if (ctap_user_presence_test() == 0)
if (ctap_user_presence_test() == 0) {
{ return U2F_SW_CONDITIONS_NOT_SATISFIED;
return U2F_SW_CONDITIONS_NOT_SATISFIED; }
}
}
count = ctap_atomic_count(0); count = ctap_atomic_count(0);
hash[0] = 0x7f; hash[0] = 0xff;
hash[1] = (count >> 16) & 0xff; hash[1] = (count >> 16) & 0xff;
hash[2] = (count >> 8) & 0xff; hash[2] = (count >> 8) & 0xff;
hash[3] = (count >> 0) & 0xff; hash[3] = (count >> 0) & 0xff;
crypto_sha256_init(); crypto_sha256_init();
crypto_sha256_update(req->app, 32); crypto_sha256_update(req->app,32);
crypto_sha256_update(&up, 1); crypto_sha256_update(&up,1);
crypto_sha256_update(hash, 4); crypto_sha256_update(hash,4);
crypto_sha256_update(req->chal, 32); crypto_sha256_update(req->chal,32);
crypto_sha256_final(hash); crypto_sha256_final(hash);
printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F, hash, 32); printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F,hash,32);
crypto_ecc256_sign(hash, 32, sig); crypto_ecc256_sign(hash, 32, sig);
u2f_response_writeback(&up,1); u2f_response_writeback(&up,1);
hash[0] = 0x7f; hash[0] = 0xff;
hash[1] = (count >> 16) & 0xff; hash[1] = (count >> 16) & 0xff;
hash[2] = (count >> 8) & 0xff; hash[2] = (count >> 8) & 0xff;
hash[3] = (count >> 0) & 0xff; hash[3] = (count >> 0) & 0xff;
@ -286,13 +263,10 @@ static int16_t u2f_register(struct u2f_register_request * req)
const uint16_t attest_size = attestation_cert_der_size; const uint16_t attest_size = attestation_cert_der_size;
if(!device_is_nfc()) if ( ! ctap_user_presence_test())
{ {
if ( ! ctap_user_presence_test()) return U2F_SW_CONDITIONS_NOT_SATISFIED;
{ }
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
}
if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1) if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1)
{ {

View File

@ -38,16 +38,16 @@
// U2F Authenticate // U2F Authenticate
#define U2F_AUTHENTICATE_CHECK 0x7 #define U2F_AUTHENTICATE_CHECK 0x7
#define U2F_AUTHENTICATE_SIGN 0x3 #define U2F_AUTHENTICATE_SIGN 0x3
#define U2F_AUTHENTICATE_SIGN_NO_USER 0x8
// Command status responses // Command status responses
#define U2F_SW_NO_ERROR 0x9000 #define U2F_SW_NO_ERROR 0x9000
#define U2F_SW_WRONG_DATA 0x6984
#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 #define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985
#define U2F_SW_INS_NOT_SUPPORTED 0x6d00 #define U2F_SW_INS_NOT_SUPPORTED 0x6d00
#define U2F_SW_WRONG_LENGTH 0x6700 #define U2F_SW_WRONG_LENGTH 0x6700
#define U2F_SW_CLASS_NOT_SUPPORTED 0x6E00 #define U2F_SW_CLASS_NOT_SUPPORTED 0x6E00
#define U2F_SW_WRONG_DATA 0x6a80 #define U2F_SW_WRONG_PAYLOAD 0x6a80
#define U2F_SW_INSUFFICIENT_MEMORY 0x9210 #define U2F_SW_INSUFFICIENT_MEMORY 0x9210
// Delay in milliseconds to wait for user input // Delay in milliseconds to wait for user input
@ -95,14 +95,9 @@ struct u2f_authenticate_request
}; };
// u2f_request send a U2F message to U2F protocol // u2f_request send a U2F message to U2F protocol
// @req U2F message // @req U2F message
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp); void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
// u2f_request send a U2F message to NFC protocol
// @req data with iso7816 apdu message
// @len data length
void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp);
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len); int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
void u2f_reset_response(); void u2f_reset_response();

View File

@ -5,7 +5,7 @@ version=${1:-master}
export PREFIX=/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/ export PREFIX=/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/
cd /solo/targets/stm32l432 cd /solo/targets/stm32l432
git fetch --tags git fetch
git checkout ${version} git checkout ${version}
version=$(git describe) version=$(git describe)
@ -35,10 +35,3 @@ build bootloader nonverifying
build bootloader verifying build bootloader verifying
build firmware hacker solo build firmware hacker solo
build firmware secure solo build firmware secure solo
pip install -U pip
pip install -U solo-python
cd ${out_dir}
bundle="bundle-hacker-${version}"
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-hacker-${version}.hex ${bundle}.hex
sha256sum ${bundle}.hex > ${bundle}.sha2

View File

@ -22,11 +22,6 @@
#include "log.h" #include "log.h"
#include "ctaphid.h" #include "ctaphid.h"
#define RK_NUM 50
struct ResidentKeyStore {
CTAP_residentKey rks[RK_NUM];
} RK_STORE;
void authenticator_initialize(); void authenticator_initialize();
@ -146,20 +141,11 @@ void usbhid_init()
int usbhid_recv(uint8_t * msg) int usbhid_recv(uint8_t * msg)
{ {
int l = udp_recv(serverfd, msg, HID_MESSAGE_SIZE); int l = udp_recv(serverfd, msg, HID_MESSAGE_SIZE);
uint8_t magic_cmd[] = "\xac\x10\x52\xca\x95\xe5\x69\xde\x69\xe0\x2e\xbf" /*if (l && l != HID_MESSAGE_SIZE)*/
"\xf3\x33\x48\x5f\x13\xf9\xb2\xda\x34\xc5\xa8\xa3" /*{*/
"\x40\x52\x66\x97\xa9\xab\x2e\x0b\x39\x4d\x8d\x04" /*printf("Error, recv'd message of wrong size %d", l);*/
"\x97\x3c\x13\x40\x05\xbe\x1a\x01\x40\xbf\xf6\x04" /*exit(1);*/
"\x5b\xb2\x6e\xb7\x7a\x73\xea\xa4\x78\x13\xf6\xb4" /*}*/
"\x9a\x72\x50\xdc";
if ( memcmp(magic_cmd, msg, 64) == 0 )
{
printf1(TAG_RED, "MAGIC REBOOT command recieved!\r\n");
memset(msg,0,64);
exit(100);
return 0;
}
return l; return l;
} }
@ -188,10 +174,6 @@ void device_init()
usbhid_init(); usbhid_init();
authenticator_initialize(); authenticator_initialize();
ctaphid_init();
ctap_init( 1 );
} }
@ -199,7 +181,7 @@ void main_loop_delay()
{ {
struct timespec ts; struct timespec ts;
ts.tv_sec = 0; ts.tv_sec = 0;
ts.tv_nsec = 1000*1000*100; ts.tv_nsec = 1000*1000*25;
nanosleep(&ts,NULL); nanosleep(&ts,NULL);
} }
@ -265,7 +247,6 @@ 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 * backup_file = "authenticator_state2.bin";
const char * rk_file = "resident_keys.bin";
void authenticator_read_state(AuthenticatorState * state) void authenticator_read_state(AuthenticatorState * state)
{ {
@ -385,24 +366,6 @@ int authenticator_is_backup_initialized()
/*}*/ /*}*/
static void sync_rk()
{
FILE * f = fopen(rk_file, "wb+");
if (f== NULL)
{
perror("fopen");
exit(1);
}
int ret = fwrite(&RK_STORE, 1, sizeof(RK_STORE), f);
fclose(f);
if (ret != sizeof(RK_STORE))
{
perror("fwrite");
exit(1);
}
}
void authenticator_initialize() void authenticator_initialize()
{ {
uint8_t header[16]; uint8_t header[16];
@ -426,22 +389,6 @@ void authenticator_initialize()
perror("fwrite"); perror("fwrite");
exit(1); exit(1);
} }
// resident_keys
f = fopen(rk_file, "rb");
if (f== NULL)
{
perror("fopen");
exit(1);
}
ret = fread(&RK_STORE, 1, sizeof(RK_STORE), f);
fclose(f);
if(ret != sizeof(RK_STORE))
{
perror("fwrite");
exit(1);
}
} }
else else
{ {
@ -480,12 +427,6 @@ void authenticator_initialize()
exit(1); exit(1);
} }
// resident_keys
memset(&RK_STORE,0xff,sizeof(RK_STORE));
sync_rk();
} }
} }
@ -494,60 +435,29 @@ void device_manage()
} }
void ctap_reset_rk() void ctap_reset_rk()
{ {
memset(&RK_STORE,0xff,sizeof(RK_STORE));
sync_rk();
} }
uint32_t ctap_rk_size() uint32_t ctap_rk_size()
{ {
return RK_NUM; printf("Warning: rk not implemented\n");
return 0;
} }
void ctap_store_rk(int index,CTAP_residentKey * rk)
void ctap_store_rk(int index, CTAP_residentKey * rk)
{ {
if (index < RK_NUM) printf("Warning: rk not implemented\n");
{
memmove(RK_STORE.rks + index, rk, sizeof(CTAP_residentKey));
sync_rk();
}
else
{
printf1(TAG_ERR,"Out of bounds for store_rk\r\n");
}
} }
void ctap_load_rk(int index,CTAP_residentKey * rk)
void ctap_load_rk(int index, CTAP_residentKey * rk)
{ {
memmove(rk, RK_STORE.rks + index, sizeof(CTAP_residentKey)); printf("Warning: rk not implemented\n");
} }
void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
void ctap_overwrite_rk(int index, CTAP_residentKey * rk)
{ {
if (index < RK_NUM) printf("Warning: rk not implemented\n");
{
memmove(RK_STORE.rks + index, rk, sizeof(CTAP_residentKey));
sync_rk();
}
else
{
printf1(TAG_ERR,"Out of bounds for store_rk\r\n");
}
} }
void device_wink() void device_wink()
{ {
printf("*WINK*\n"); printf("*WINK*\n");
} }
bool device_is_nfc()
{
return 0;
}

1
python-fido2 Submodule

Submodule python-fido2 added at 329434fdd4

View File

@ -5,7 +5,7 @@ endif
APPMAKE=build/application.mk APPMAKE=build/application.mk
BOOTMAKE=build/bootloader.mk BOOTMAKE=build/bootloader.mk
merge_hex=solo mergehex merge_hex=../../tools/solotool.py mergehex
.PHONY: all all-hacker all-locked debugboot-app debugboot-boot boot-sig-checking boot-no-sig build-release-locked build-release build-release build-hacker build-debugboot clean clean2 flash flash_dfu flashboot detach cbor test .PHONY: all all-hacker all-locked debugboot-app debugboot-boot boot-sig-checking boot-no-sig build-release-locked build-release build-release build-hacker build-debugboot clean clean2 flash flash_dfu flashboot detach cbor test
@ -15,12 +15,6 @@ merge_hex=solo mergehex
firmware-hacker: firmware-hacker:
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' $(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
firmware-hacker-debug-1:
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=1 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
firmware-hacker-debug-2:
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=2 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
firmware-secure: firmware-secure:
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DUSE_SOLOKEYS_CERT -DFLASH_ROP=2' $(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DUSE_SOLOKEYS_CERT -DFLASH_ROP=2'

View File

@ -55,7 +55,7 @@
#define SOLO_PRODUCT_NAME "Solo Bootloader " SOLO_VERSION #define SOLO_PRODUCT_NAME "Solo Bootloader " SOLO_VERSION
void printing_init(); void printing_init();
void hw_init(int lf); void hw_init(void);
// Trigger software reset // Trigger software reset
void device_reboot(); void device_reboot();

View File

@ -8,10 +8,6 @@
#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"
@ -21,13 +17,14 @@
#include "ctap.h" #include "ctap.h"
#include "app.h" #include "app.h"
#include "memory_layout.h" #include "memory_layout.h"
#include "init.h" #include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx.h"
uint8_t REBOOT_FLAG = 0; uint8_t REBOOT_FLAG = 0;
void BOOT_boot(void) void BOOT_boot(void)
{ {
typedef void (*pFunction)(void); typedef void (*pFunction)(void);
@ -72,16 +69,7 @@ int main()
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();
@ -119,13 +107,7 @@ int main()
#ifdef SOLO_HACKER #ifdef SOLO_HACKER
start_bootloader: start_bootloader:
#endif #endif
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

@ -2,7 +2,7 @@ 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 += src/fifo.c src/crypto.c src/attestation.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)
@ -14,7 +14,6 @@ SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c
# Crypto libs # Crypto libs
SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c ../../crypto/tiny-AES-c/aes.c 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
OBJ1=$(SRC:.c=.o) OBJ1=$(SRC:.c=.o)
OBJ=$(OBJ1:.s=.o) OBJ=$(OBJ1:.s=.o)
@ -22,7 +21,6 @@ OBJ=$(OBJ1:.s=.o)
INC = -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions INC = -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -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
SEARCH=-L../../tinycbor/lib SEARCH=-L../../tinycbor/lib
@ -43,14 +41,12 @@ DEBUG=0
endif endif
DEFINES = -DDEBUG_LEVEL=$(DEBUG) -D$(CHIP) -DAES256=1 -DUSE_FULL_LL_DRIVER -DAPP_CONFIG=\"app.h\" $(EXTRA_DEFINES) DEFINES = -DDEBUG_LEVEL=$(DEBUG) -D$(CHIP) -DAES256=1 -DUSE_FULL_LL_DRIVER -DAPP_CONFIG=\"app.h\" $(EXTRA_DEFINES)
# DEFINES += -DTEST_SOLO_STM32 -DTEST -DTEST_FIFO=1
CFLAGS=$(INC) -c $(DEFINES) -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fdata-sections -ffunction-sections \ CFLAGS=$(INC) -c $(DEFINES) -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fdata-sections -ffunction-sections $(HW) -g $(VERSION_FLAGS)
-fomit-frame-pointer $(HW) -g $(VERSION_FLAGS)
LDFLAGS_LIB=$(HW) $(SEARCH) -specs=nano.specs -specs=nosys.specs -Wl,--gc-sections -u _printf_float -lnosys LDFLAGS_LIB=$(HW) $(SEARCH) -specs=nano.specs -specs=nosys.specs -Wl,--gc-sections -u _printf_float -lnosys
LDFLAGS=$(HW) $(LDFLAGS_LIB) -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref -Wl,-Bstatic -ltinycbor LDFLAGS=$(HW) $(LDFLAGS_LIB) -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref -Wl,-Bstatic -ltinycbor
ECC_CFLAGS = $(CFLAGS) -DuECC_PLATFORM=5 -DuECC_OPTIMIZATION_LEVEL=4 -DuECC_SQUARE_FUNC=1 -DuECC_SUPPORT_COMPRESSED_POINT=0
.PRECIOUS: %.o .PRECIOUS: %.o
@ -61,7 +57,7 @@ all: $(TARGET).elf
$(CC) $^ $(HW) -Os $(CFLAGS) -o $@ $(CC) $^ $(HW) -Os $(CFLAGS) -o $@
../../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 $(CFLAGS) -o $@
%.o: %.s %.o: %.s
$(CC) $^ $(HW) -Os $(CFLAGS) -o $@ $(CC) $^ $(HW) -Os $(CFLAGS) -o $@
@ -70,7 +66,6 @@ all: $(TARGET).elf
$(CC) $^ $(HW) $(LDFLAGS) -o $@ $(CC) $^ $(HW) $(LDFLAGS) -o $@
%.hex: %.elf %.hex: %.elf
$(SZ) $^
$(CP) -O ihex $^ $(TARGET).hex $(CP) -O ihex $^ $(TARGET).hex
clean: clean:

View File

@ -13,7 +13,6 @@ SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2
# Crypto libs # Crypto libs
SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c
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)
@ -22,7 +21,6 @@ OBJ=$(OBJ1:.s=.o)
INC = -Ibootloader/ -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions INC = -Ibootloader/ -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -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
ifndef LDSCRIPT ifndef LDSCRIPT
LDSCRIPT=linker/bootloader_stm32l4xx.ld LDSCRIPT=linker/bootloader_stm32l4xx.ld

View File

@ -6,7 +6,7 @@ AR=$(PREFIX)arm-none-eabi-ar
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 \
lib/stm32l4xx_ll_usb.c lib/stm32l4xx_ll_utils.c lib/stm32l4xx_ll_pwr.c \ lib/stm32l4xx_ll_usb.c lib/stm32l4xx_ll_utils.c lib/stm32l4xx_ll_pwr.c \
lib/stm32l4xx_ll_usart.c lib/stm32l4xx_ll_spi.c lib/stm32l4xx_ll_usart.c
USB_LIB := lib/usbd/usbd_cdc.c lib/usbd/usbd_cdc_if.c lib/usbd/usbd_composite.c \ USB_LIB := lib/usbd/usbd_cdc.c lib/usbd/usbd_cdc_if.c lib/usbd/usbd_composite.c \
lib/usbd/usbd_conf.c lib/usbd/usbd_core.c lib/usbd/usbd_ioreq.c \ lib/usbd/usbd_conf.c lib/usbd/usbd_core.c lib/usbd/usbd_ioreq.c \

View File

@ -1,307 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_ll_spi.c
* @author MCD Application Team
* @brief SPI LL module driver.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if defined(USE_FULL_LL_DRIVER)
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_ll_spi.h"
#include "stm32l4xx_ll_bus.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined (SPI1) || defined (SPI2) || defined (SPI3)
/** @addtogroup SPI_LL
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup SPI_LL_Private_Constants SPI Private Constants
* @{
*/
/* SPI registers Masks */
#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \
SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \
SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_CRCL | \
SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \
SPI_CR1_BIDIMODE)
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup SPI_LL_Private_Macros SPI Private Macros
* @{
*/
#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \
|| ((__VALUE__) == LL_SPI_SIMPLEX_RX) \
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX))
#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \
|| ((__VALUE__) == LL_SPI_MODE_SLAVE))
#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_4BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT))
#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \
|| ((__VALUE__) == LL_SPI_POLARITY_HIGH))
#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \
|| ((__VALUE__) == LL_SPI_PHASE_2EDGE))
#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \
|| ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \
|| ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT))
#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256))
#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \
|| ((__VALUE__) == LL_SPI_MSB_FIRST))
#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \
|| ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE))
#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U)
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup SPI_LL_Exported_Functions
* @{
*/
/** @addtogroup SPI_LL_EF_Init
* @{
*/
/**
* @brief De-initialize the SPI registers to their default reset values.
* @param SPIx SPI Instance
* @retval An ErrorStatus enumeration value:
* - SUCCESS: SPI registers are de-initialized
* - ERROR: SPI registers are not de-initialized
*/
ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx)
{
ErrorStatus status = ERROR;
/* Check the parameters */
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
#if defined(SPI1)
if (SPIx == SPI1)
{
/* Force reset of SPI clock */
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
/* Release reset of SPI clock */
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
status = SUCCESS;
}
#endif /* SPI1 */
#if defined(SPI2)
if (SPIx == SPI2)
{
/* Force reset of SPI clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
/* Release reset of SPI clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
status = SUCCESS;
}
#endif /* SPI2 */
#if defined(SPI3)
if (SPIx == SPI3)
{
/* Force reset of SPI clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3);
/* Release reset of SPI clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3);
status = SUCCESS;
}
#endif /* SPI3 */
return status;
}
/**
* @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct.
* @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0),
* SPI IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
* @param SPIx SPI Instance
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
* @retval An ErrorStatus enumeration value. (Return always SUCCESS)
*/
ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct)
{
ErrorStatus status = ERROR;
/* Check the SPI Instance SPIx*/
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
/* Check the SPI parameters from SPI_InitStruct*/
assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection));
assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode));
assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth));
assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity));
assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase));
assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS));
assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate));
assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder));
assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation));
if (LL_SPI_IsEnabled(SPIx) == 0x00000000U)
{
/*---------------------------- SPIx CR1 Configuration ------------------------
* Configure SPIx CR1 with parameters:
* - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits
* - Master/Slave Mode: SPI_CR1_MSTR bit
* - ClockPolarity: SPI_CR1_CPOL bit
* - ClockPhase: SPI_CR1_CPHA bit
* - NSS management: SPI_CR1_SSM bit
* - BaudRate prescaler: SPI_CR1_BR[2:0] bits
* - BitOrder: SPI_CR1_LSBFIRST bit
* - CRCCalculation: SPI_CR1_CRCEN bit
*/
MODIFY_REG(SPIx->CR1,
SPI_CR1_CLEAR_MASK,
SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode |
SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase |
SPI_InitStruct->NSS | SPI_InitStruct->BaudRate |
SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation);
/*---------------------------- SPIx CR2 Configuration ------------------------
* Configure SPIx CR2 with parameters:
* - DataWidth: DS[3:0] bits
* - NSS management: SSOE bit
*/
MODIFY_REG(SPIx->CR2,
SPI_CR2_DS | SPI_CR2_SSOE,
SPI_InitStruct->DataWidth | (SPI_InitStruct->NSS >> 16U));
/*---------------------------- SPIx CRCPR Configuration ----------------------
* Configure SPIx CRCPR with parameters:
* - CRCPoly: CRCPOLY[15:0] bits
*/
if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE)
{
assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly));
LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly);
}
status = SUCCESS;
}
return status;
}
/**
* @brief Set each @ref LL_SPI_InitTypeDef field to default value.
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
* whose fields will be set to default values.
* @retval None
*/
void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct)
{
/* Set SPI_InitStruct fields to default values */
SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE;
SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT;
SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct->CRCPoly = 7U;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

File diff suppressed because it is too large Load Diff

View File

@ -821,16 +821,12 @@ void USBD_CtlError( USBD_HandleTypeDef *pdev ,
* @param len : descriptor length * @param len : descriptor length
* @retval None * @retval None
*/ */
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t unicode_size, uint16_t *len) void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
{ {
uint8_t idx = 0U; uint8_t idx = 0U;
if (desc != NULL) if (desc != NULL)
{ {
if ((idx + 4) >= unicode_size)
{
return;
}
*len = (uint16_t)USBD_GetLen(desc) * 2U + 2U; *len = (uint16_t)USBD_GetLen(desc) * 2U + 2U;
unicode[idx++] = *(uint8_t *)(void *)len; unicode[idx++] = *(uint8_t *)(void *)len;
unicode[idx++] = USB_DESC_TYPE_STRING; unicode[idx++] = USB_DESC_TYPE_STRING;

View File

@ -108,7 +108,7 @@ void USBD_CtlError (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata); void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata);
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t unicode_size, uint16_t *len); void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
/** /**
* @} * @}
*/ */

View File

@ -108,7 +108,7 @@ const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC]=
HIBYTE(USBD_LANGID_STRING), HIBYTE(USBD_LANGID_STRING),
}; };
uint8_t USBD_StrDesc[48]; uint8_t USBD_StrDesc[32];
/** /**
* @brief Returns the device descriptor. * @brief Returns the device descriptor.
@ -142,7 +142,7 @@ uint8_t *USBD_HID_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
*/ */
uint8_t *USBD_HID_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) uint8_t *USBD_HID_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{ {
USBD_GetString((uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, sizeof(USBD_StrDesc), length); USBD_GetString((uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);
return USBD_StrDesc; return USBD_StrDesc;
} }
@ -154,7 +154,7 @@ uint8_t *USBD_HID_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length
*/ */
uint8_t *USBD_HID_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) uint8_t *USBD_HID_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{ {
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, sizeof(USBD_StrDesc), length); USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc; return USBD_StrDesc;
} }
@ -192,6 +192,6 @@ uint8_t *USBD_HID_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
} }
USBD_GetString((uint8_t *)uuid_str, USBD_StrDesc, sizeof(USBD_StrDesc), length); USBD_GetString((uint8_t *)uuid_str, USBD_StrDesc, length);
return USBD_StrDesc; return USBD_StrDesc;
} }

View File

@ -1,366 +0,0 @@
#include <string.h>
#include "stm32l4xx_ll_spi.h"
#include "ams.h"
#include "log.h"
#include "util.h"
#include "device.h"
#include "nfc.h"
static void flush_rx()
{
while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0)
{
LL_SPI_ReceiveData8(SPI1);
}
}
static void wait_for_tx()
{
// while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1)
// ;
while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY)
;
}
static void wait_for_rx()
{
while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0)
;
}
void ams_print_device(AMS_DEVICE * dev)
{
printf1(TAG_NFC, "AMS_DEVICE:\r\n");
printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf);
printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0);
printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1);
printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2);
printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status);
printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status);
printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0);
printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1);
printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0);
printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1);
printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2);
printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1);
printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr);
printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type);
printf1(TAG_NFC, " product_subtype:%02x\r\n",dev->regs.product_subtype);
printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj);
printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min);
}
static uint8_t send_recv(uint8_t b)
{
wait_for_tx();
LL_SPI_TransmitData8(SPI1, b);
wait_for_rx();
b = LL_SPI_ReceiveData8(SPI1);
return b;
}
void ams_write_reg(uint8_t addr, uint8_t tx)
{
send_recv(0x00| addr);
send_recv(tx);
UNSELECT();
SELECT();
}
uint8_t ams_read_reg(uint8_t addr)
{
send_recv(0x20| (addr & 0x1f));
uint8_t data = send_recv(0);
UNSELECT();
SELECT();
return data;
}
// data must be 14 bytes long
void read_reg_block(AMS_DEVICE * dev)
{
int i;
uint8_t mode = 0x20 | (4 );
flush_rx();
send_recv(mode);
for (i = 0x04; i < 0x0d; i++)
{
dev->buf[i] = send_recv(0);
}
UNSELECT();
SELECT();
}
void ams_read_buffer(uint8_t * data, int len)
{
send_recv(0xa0);
while(len--)
{
*data++ = send_recv(0x00);
}
UNSELECT();
SELECT();
}
void ams_write_buffer(uint8_t * data, int len)
{
send_recv(0x80);
while(len--)
{
send_recv(*data++);
}
UNSELECT();
SELECT();
}
// data must be 4 bytes
void ams_read_eeprom_block(uint8_t block, uint8_t * data)
{
send_recv(0x7f);
send_recv(block << 1);
data[0] = send_recv(0);
data[1] = send_recv(0);
data[2] = send_recv(0);
data[3] = send_recv(0);
UNSELECT();
SELECT();
}
// data must be 4 bytes
void ams_write_eeprom_block(uint8_t block, uint8_t * data)
{
send_recv(0x40);
send_recv(block << 1);
send_recv(data[0]);
send_recv(data[1]);
send_recv(data[2]);
send_recv(data[3]);
UNSELECT();
SELECT();
}
void ams_write_command(uint8_t cmd)
{
send_recv(0xc0 | cmd);
UNSELECT();
SELECT();
}
const char * ams_get_state_string(uint8_t regval)
{
if (regval & AMS_STATE_INVALID)
{
return "STATE_INVALID";
}
switch (regval & AMS_STATE_MASK)
{
case AMS_STATE_OFF:
return "STATE_OFF";
case AMS_STATE_SENSE:
return "STATE_SENSE";
case AMS_STATE_RESOLUTION:
return "STATE_RESOLUTION";
case AMS_STATE_RESOLUTION_L2:
return "STATE_RESOLUTION_L2";
case AMS_STATE_SELECTED:
return "STATE_SELECTED";
case AMS_STATE_SECTOR2:
return "STATE_SECTOR2";
case AMS_STATE_SECTORX_2:
return "STATE_SECTORX_2";
case AMS_STATE_SELECTEDX:
return "STATE_SELECTEDX";
case AMS_STATE_SENSEX_L2:
return "STATE_SENSEX_L2";
case AMS_STATE_SENSEX:
return "STATE_SENSEX";
case AMS_STATE_SLEEP:
return "STATE_SLEEP";
}
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)
{
#if DEBUG_LEVEL
uint32_t tag = (TAG_NFC)|(TAG_NO_TAG);
printf1(TAG_NFC," ");
if (int0 & AMS_INT_XRF)
printf1(tag," XRF");
if (int0 & AMS_INT_TXE)
printf1(tag," TXE");
if (int0 & AMS_INT_RXE)
printf1(tag," RXE");
if (int0 & AMS_INT_EER_RF)
printf1(tag," EER_RF");
if (int0 & AMS_INT_EEW_RF)
printf1(tag," EEW_RF");
if (int0 & AMS_INT_SLP)
printf1(tag," SLP");
if (int0 & AMS_INT_WU_A)
printf1(tag," WU_A");
if (int0 & AMS_INT_INIT)
printf1(tag," INIT");
printf1(tag,"\r\n");
#endif
}
void ams_print_int1(uint8_t int0)
{
#if DEBUG_LEVEL
uint32_t tag = (TAG_NFC)|(TAG_NO_TAG);
printf1(TAG_NFC," ");
if (int0 & AMS_INT_ACC_ERR)
printf1(tag," ACC_ERR");
if (int0 & AMS_INT_EEAC_ERR)
printf1(tag," EEAC_ERR");
if (int0 & AMS_INT_IO_EEWR)
printf1(tag," IO_EEWR");
if (int0 & AMS_INT_BF_ERR)
printf1(tag," BF_ERR");
if (int0 & AMS_INT_CRC_ERR)
printf1(tag," CRC_ERR");
if (int0 & AMS_INT_PAR_ERR)
printf1(tag," PAR_ERR");
if (int0 & AMS_INT_FRM_ERR)
printf1(tag," FRM_ERR");
if (int0 & AMS_INT_RXS)
printf1(tag," RXS");
printf1(tag,"\r\n");
#endif
}
void ams_init()
{
LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN);
LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW);
LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE);
LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_Enable(SPI1);
// delay(10);
SELECT();
delay(1);
}
void ams_configure()
{
// Should not be used during passive operation.
uint8_t block[4];
// check connection
uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE);
if (productType != 0x14)
{
printf1(TAG_ERR, "Have wrong product type [0x%02x]. AMS3956 connection error.\n", productType);
}
printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType);
ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block);
printf1(TAG_NFC,"UID: 3F 14 02 - "); dump_hex1(TAG_NFC,block,4);
ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4);
uint8_t sense1 = 0x44;
uint8_t sense2 = 0x00;
uint8_t selr = 0x20; // SAK
if(block[0] != sense1 || block[1] != sense2 || block[2] != selr)
{
printf1(TAG_NFC,"Writing config block 0\r\n");
block[0] = sense1;
block[1] = sense2;
block[2] = selr;
block[3] = 0x00;
ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
UNSELECT();
delay(10);
SELECT();
delay(10);
ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block);
printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4);
}
ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block);
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_cfg2 = AMS_CFG2_TUN_MOD;
if (block[0] != ic_cfg1 || block[1] != ic_cfg2)
{
printf1(TAG_NFC,"Writing config block 1\r\n");
ams_write_reg(AMS_REG_IC_CONF1,ic_cfg1);
ams_write_reg(AMS_REG_IC_CONF2,ic_cfg2);
// set IC_CFG1
block[0] = ic_cfg1;
// set IC_CFG2
block[1] = ic_cfg2;
// mask interrupt bits
block[2] = 0x80;
block[3] = 0;
ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block);
UNSELECT();
delay(10);
SELECT();
delay(10);
ams_read_eeprom_block(0x7F, block);
printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4);
}
}

View File

@ -1,162 +0,0 @@
// AS3956 interface
// https://ams.com/as3956
// https://ams.com/documents/20143/36005/AS3956_DS000546_7-00.pdf
#ifndef _AMS_H_
#define _AMS_H_
#include <stdint.h>
#include <stdbool.h>
#include "stm32l4xx_ll_gpio.h"
typedef union
{
uint8_t buf[0x20];
struct {
uint8_t io_conf; // 0x00
uint8_t ic_conf0; // 0x01
uint8_t ic_conf1; // 0x02
uint8_t ic_conf2; // 0x03
uint8_t rfid_status; // 0x04
uint8_t ic_status; // 0x05
uint8_t _nc0[2]; // 0x06 - 0x07
uint8_t mask_int0; // 0x08
uint8_t mask_int1; // 0x09
uint8_t int0; // 0x0a
uint8_t int1; // 0x0b
uint8_t buffer_status2; // 0x0c
uint8_t buffer_status1; // 0x0d
uint8_t last_nfc_addr; // 0x0e
uint8_t _nc1[0x1b - 0x0f + 1]; // 0x0f - 0x1b
uint8_t product_type; // 0x1c
uint8_t product_subtype; // 0x1d
uint8_t version_maj; // 0x1e
uint8_t version_min; // 0x1f
} regs;
} __attribute__((packed)) AMS_DEVICE;
#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
void ams_init();
void ams_configure();
void ams_read_buffer(uint8_t * data, int len);
void ams_write_buffer(uint8_t * data, int len);
void ams_write_command(uint8_t cmd);
void read_reg_block(AMS_DEVICE * dev);
uint8_t ams_read_reg(uint8_t addr);
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_IC_CONF0 0x01
#define AMS_REG_IC_CONF1 0x02
#define AMS_REG_IC_CONF2 0x03
#define AMS_RFCFG_EN 0x80
#define AMS_TUN_MOD 0x40
#define AMS_REG_RFID_STATUS 0x04
#define AMS_HF_PON 0x80
#define AMS_STATE_MASK 0x78
#define AMS_STATE_INVALID 0x04
#define AMS_STATE_OFF (0 << 3)
#define AMS_STATE_SENSE (1 << 3)
#define AMS_STATE_RESOLUTION (3 << 3)
#define AMS_STATE_RESOLUTION_L2 (2 << 3)
#define AMS_STATE_SELECTED (6 << 3)
#define AMS_STATE_SECTOR2 (7 << 3)
#define AMS_STATE_SECTORX_2 (0xf << 3)
#define AMS_STATE_SELECTEDX (0xe << 3)
#define AMS_STATE_SENSEX_L2 (0xa << 3)
#define AMS_STATE_SENSEX (0xb << 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_INT_XRF (1<<0)
#define AMS_INT_TXE (1<<1)
#define AMS_INT_RXE (1<<2)
#define AMS_INT_EER_RF (1<<3)
#define AMS_INT_EEW_RF (1<<4)
#define AMS_INT_SLP (1<<5)
#define AMS_INT_WU_A (1<<6)
#define AMS_INT_INIT (1<<7)
#define AMS_REG_INT1 0x0b
#define AMS_INT_ACC_ERR (1<<0)
#define AMS_INT_EEAC_ERR (1<<1)
#define AMS_INT_IO_EEWR (1<<2)
#define AMS_INT_BF_ERR (1<<3)
#define AMS_INT_CRC_ERR (1<<4)
#define AMS_INT_PAR_ERR (1<<5)
#define AMS_INT_FRM_ERR (1<<6)
#define AMS_INT_RXS (1<<7)
#define AMS_REG_BUF2 0x0c
#define AMS_BUF_LEN_MASK 0x1f
#define AMS_BUF_INVALID 0x80
#define AMS_REG_BUF1 0x0d
// ... //
#define AMS_REG_PRODUCT_TYPE 0x1c
#define AMS_REG_PRODUCT_SUBTYPE 0x1d
#define AMS_REG_VERSION_MAJOR 0x1e
#define AMS_REG_VERSION_MINOR 0x1f
#define AMS_CONFIG_UID_ADDR 0x00
#define AMS_CONFIG_BLOCK0_ADDR 0x7e
#define AMS_CONFIG_BLOCK1_ADDR 0x7f
#define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<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_VOLTAGE_LEVEL_2V6 (0x07<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V7 (0x08<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V8 (0x09<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_2V9 (0x0a<<2)
#define AMS_CFG1_VOLTAGE_LEVEL_3V0 (0x0b<<2)
#define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00
#define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01
#define AMS_CFG1_OUTPUT_RESISTANCE_50 0x02
#define AMS_CFG1_OUTPUT_RESISTANCE_25 0x03
#define AMS_CFG2_RFCFG_EN (1<<7)
#define AMS_CFG2_TUN_MOD (1<<6)
#define AMS_CMD_DEFAULT 0x02
#define AMS_CMD_CLEAR_BUFFER 0x04
#define AMS_CMD_RESTART_TRANSCEIVER 0x06
#define AMS_CMD_DIS_EN_TRANSCEIVER 0x07
#define AMS_CMD_TRANSMIT_BUFFER 0x08
#define AMS_CMD_TRANSMIT_ACK 0x09
#define AMS_CMD_TRANSMIT_NACK0 0x0A
#define AMS_CMD_TRANSMIT_NACK1 0x0B
#define AMS_CMD_TRANSMIT_NACK4 0x0D
#define AMS_CMD_TRANSMIT_NACK5 0x0C
#define AMS_CMD_SLEEP 0x10
#define AMS_CMD_SENSE 0x11
#define AMS_CMD_SENSE_SLEEP 0x12
#endif

View File

@ -30,7 +30,6 @@
// #define DISABLE_CTAPHID_WINK // #define DISABLE_CTAPHID_WINK
// #define DISABLE_CTAPHID_CBOR // #define DISABLE_CTAPHID_CBOR
#define ENABLE_SERIAL_PRINTING
#if defined(SOLO_HACKER) #if defined(SOLO_HACKER)
#define SOLO_PRODUCT_NAME "Solo Hacker " SOLO_VERSION #define SOLO_PRODUCT_NAME "Solo Hacker " SOLO_VERSION
@ -39,7 +38,7 @@
#endif #endif
void printing_init(); void printing_init();
void hw_init(int lf); void hw_init(void);
//#define TEST //#define TEST
//#define TEST_POWER //#define TEST_POWER
@ -64,12 +63,6 @@ void hw_init(int lf);
#define SOLO_BUTTON_PORT GPIOA #define SOLO_BUTTON_PORT GPIOA
#define SOLO_BUTTON_PIN LL_GPIO_PIN_0 #define SOLO_BUTTON_PIN LL_GPIO_PIN_0
#define SOLO_AMS_CS_PORT GPIOB
#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

@ -24,9 +24,6 @@
#include "aes.h" #include "aes.h"
#include "ctap.h" #include "ctap.h"
#include "device.h" #include "device.h"
// stuff for SHA512
#include "sha2.h"
#include "blockwise.h"
#include APP_CONFIG #include APP_CONFIG
#include "log.h" #include "log.h"
#include "memory_layout.h" #include "memory_layout.h"
@ -51,7 +48,6 @@ typedef enum
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;
@ -66,9 +62,6 @@ void crypto_sha256_init()
sha256_init(&sha256_ctx); sha256_init(&sha256_ctx);
} }
void crypto_sha512_init() {
cf_sha512_init(&sha512_ctx);
}
void crypto_load_master_secret(uint8_t * key) void crypto_load_master_secret(uint8_t * key)
{ {
@ -93,10 +86,6 @@ 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);
@ -107,11 +96,6 @@ 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];

View File

@ -10,7 +10,6 @@
#include "stm32l4xx_ll_gpio.h" #include "stm32l4xx_ll_gpio.h"
#include "stm32l4xx_ll_tim.h" #include "stm32l4xx_ll_tim.h"
#include "stm32l4xx_ll_usart.h" #include "stm32l4xx_ll_usart.h"
#include "stm32l4xx_ll_pwr.h"
#include "usbd_hid.h" #include "usbd_hid.h"
#include APP_CONFIG #include APP_CONFIG
@ -27,11 +26,6 @@
#include "memory_layout.h" #include "memory_layout.h"
#include "stm32l4xx_ll_iwdg.h" #include "stm32l4xx_ll_iwdg.h"
#include "usbd_cdc_if.h" #include "usbd_cdc_if.h"
#include "nfc.h"
#include "init.h"
#define LOW_FREQUENCY 1
#define HIGH_FREQUENCY 0
void wait_for_usb_tether(); void wait_for_usb_tether();
@ -40,8 +34,6 @@ 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;
static bool haveNFC = 0;
static 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))
@ -58,13 +50,6 @@ void TIM6_DAC_IRQHandler()
ctaphid_update_status(__device_status); ctaphid_update_status(__device_status);
} }
} }
#ifndef IS_BOOTLOADER
// NFC sending WTX if needs
if (device_is_nfc())
{
WTX_timer_exec();
}
#endif
} }
// Global USB interrupt handler // Global USB interrupt handler
@ -106,42 +91,32 @@ 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);
LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP);
hw_init(LOW_FREQUENCY); #ifndef IS_BOOTLOADER
isLowFreq = 0;
haveNFC = nfc_init();
if (haveNFC)
{
printf1(TAG_NFC, "Have NFC\r\n");
}
else
{
printf1(TAG_NFC, "Have NO NFC\r\n");
hw_init(HIGH_FREQUENCY);
isLowFreq = 0;
}
usbhid_init();
ctaphid_init();
ctap_init();
#if BOOT_TO_DFU #if BOOT_TO_DFU
flash_option_bytes_init(1); flash_option_bytes_init(1);
#else #else
flash_option_bytes_init(0); flash_option_bytes_init(0);
#endif
#endif #endif
printf1(TAG_GEN,"hello solo\r\n");
} }
bool device_is_nfc() void usb_init(void);
void usbhid_init()
{ {
return haveNFC; usb_init();
#if DEBUG_LEVEL>1
wait_for_usb_tether();
#endif
} }
void wait_for_usb_tether() void wait_for_usb_tether()
@ -155,26 +130,6 @@ void wait_for_usb_tether()
; ;
} }
void usbhid_init()
{
if (!isLowFreq)
{
init_usb();
#if DEBUG_LEVEL>1
wait_for_usb_tether();
#endif
}
else
{
}
}
int usbhid_recv(uint8_t * msg) int usbhid_recv(uint8_t * msg)
{ {
if (fifo_hidmsg_size()) if (fifo_hidmsg_size())
@ -411,7 +366,6 @@ uint32_t ctap_atomic_count(int sel)
} }
void device_manage() void device_manage()
{ {
#if NON_BLOCK_PRINTING #if NON_BLOCK_PRINTING
@ -432,10 +386,6 @@ void device_manage()
} }
} }
#endif #endif
#ifndef IS_BOOTLOADER
// if(device_is_nfc())
nfc_loop();
#endif
} }
static int handle_packets() static int handle_packets()
@ -593,7 +543,7 @@ void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
memmove(tmppage + (sizeof(CTAP_residentKey) * index) % PAGE_SIZE, rk, sizeof(CTAP_residentKey)); memmove(tmppage + (sizeof(CTAP_residentKey) * index) % PAGE_SIZE, rk, sizeof(CTAP_residentKey));
flash_erase_page(page); flash_erase_page(page);
flash_write(flash_addr(page), tmppage, PAGE_SIZE); flash_write(flash_addr(page), tmppage, ((sizeof(CTAP_residentKey) * (index + 1)) % PAGE_SIZE) );
} }
else else
{ {

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +0,0 @@
/*
* 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 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

@ -1,799 +0,0 @@
#include <string.h>
#include "stm32l4xx.h"
#include "nfc.h"
#include "ams.h"
#include "log.h"
#include "util.h"
#include "device.h"
#include "u2f.h"
#include "crypto.h"
#include "ctap_errors.h"
#define IS_IRQ_ACTIVE() (1 == (LL_GPIO_ReadInputPort(SOLO_AMS_IRQ_PORT) & SOLO_AMS_IRQ_PIN))
// Capability container
const CAPABILITY_CONTAINER NFC_CC = {
.cclen_hi = 0x00, .cclen_lo = 0x0f,
.version = 0x20,
.MLe_hi = 0x00, .MLe_lo = 0x7f,
.MLc_hi = 0x00, .MLc_lo = 0x7f,
.tlv = { 0x04,0x06,
0xe1,0x04,
0x00,0x7f,
0x00,0x00 }
};
// 13 chars
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
{
uint8_t max_frame_size;
uint8_t cid;
uint8_t block_num;
uint8_t selected_applet;
} NFC_STATE;
void nfc_state_init()
{
memset(&NFC_STATE,0,sizeof(NFC_STATE));
NFC_STATE.max_frame_size = 32;
NFC_STATE.block_num = 1;
}
bool nfc_init()
{
uint32_t t1;
nfc_state_init();
ams_init();
// Detect if we are powered by NFC field by listening for a message for
// first 10 ms.
t1 = millis();
while ((millis() - t1) < 10)
{
if (nfc_loop() > 0)
return 1;
}
// Under USB power. Configure AMS chip.
ams_configure();
return 0;
}
void process_int0(uint8_t int0)
{
}
bool ams_wait_for_tx(uint32_t timeout_ms)
{
uint32_t tstart = millis();
while (tstart + timeout_ms > millis())
{
uint8_t int0 = ams_read_reg(AMS_REG_INT0);
if (int0) process_int0(int0);
if (int0 & AMS_INT_TXE)
return true;
delay(1);
}
return false;
}
bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, int *dlen)
{
uint8_t buf[32];
*dlen = 0;
uint32_t tstart = millis();
while (tstart + timeout_ms > millis())
{
uint8_t int0 = ams_read_reg(AMS_REG_INT0);
uint8_t buffer_status2 = ams_read_reg(AMS_REG_BUF2);
if (buffer_status2 && (int0 & AMS_INT_RXE))
{
if (buffer_status2 & AMS_BUF_INVALID)
{
printf1(TAG_NFC,"Buffer being updated!\r\n");
}
else
{
uint8_t len = buffer_status2 & AMS_BUF_LEN_MASK;
ams_read_buffer(buf, len);
printf1(TAG_NFC_APDU, ">> ");
dump_hex1(TAG_NFC_APDU, buf, len);
*dlen = MIN(32, MIN(maxlen, len));
memcpy(data, buf, *dlen);
return true;
}
}
delay(1);
}
return false;
}
void nfc_write_frame(uint8_t * data, uint8_t len)
{
if (len > 32)
{
len = 32;
}
ams_write_command(AMS_CMD_CLEAR_BUFFER);
ams_write_buffer(data,len);
ams_write_command(AMS_CMD_TRANSMIT_BUFFER);
printf1(TAG_NFC_APDU, "<< ");
dump_hex1(TAG_NFC_APDU, data, len);
}
bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t resp)
{
uint8_t res[32];
if (len > 32 - 3)
return false;
res[0] = NFC_CMD_IBLOCK | (req0 & 3);
if (len && data)
memcpy(&res[1], data, len);
res[len + 1] = resp >> 8;
res[len + 2] = resp & 0xff;
nfc_write_frame(res, 3 + len);
return true;
}
bool nfc_write_response(uint8_t req0, uint16_t resp)
{
return nfc_write_response_ex(req0, NULL, 0, resp);
}
void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len)
{
uint8_t res[32 + 2];
int sendlen = 0;
uint8_t iBlock = NFC_CMD_IBLOCK | (req0 & 3);
if (len <= 31)
{
uint8_t res[32] = {0};
res[0] = iBlock;
if (len && data)
memcpy(&res[1], data, len);
nfc_write_frame(res, len + 1);
} else {
do {
// transmit I block
int vlen = MIN(31, len - sendlen);
res[0] = iBlock;
memcpy(&res[1], &data[sendlen], vlen);
// if not a last block
if (vlen + sendlen < len)
{
res[0] |= 0x10;
}
// send data
nfc_write_frame(res, vlen + 1);
sendlen += vlen;
// wait for transmit (32 bytes aprox 2,5ms)
// if (!ams_wait_for_tx(10))
// {
// printf1(TAG_NFC, "TX timeout. slen: %d \r\n", sendlen);
// break;
// }
// if needs to receive R block (not a last block)
if (res[0] & 0x10)
{
uint8_t recbuf[32] = {0};
int reclen;
if (!ams_receive_with_timeout(100, recbuf, sizeof(recbuf), &reclen))
{
printf1(TAG_NFC, "R block RX timeout %d/%d.\r\n",sendlen,len);
break;
}
if (reclen != 1)
{
printf1(TAG_NFC, "R block length error. len: %d. %d/%d \r\n", reclen,sendlen,len);
dump_hex1(TAG_NFC, recbuf, reclen);
break;
}
if (((recbuf[0] & 0x01) == (res[0] & 1)) && ((recbuf[0] & 0xf6) == 0xa2))
{
printf1(TAG_NFC, "R block error. txdata: %02x rxdata: %02x \r\n", res[0], recbuf[0]);
break;
}
}
iBlock ^= 0x01;
} while (sendlen < len);
}
}
// WTX on/off:
// sends/receives WTX frame to reader every `WTX_time` time in ms
// works via timer interrupts
// WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16>
static bool WTX_sent;
static bool WTX_fail;
static uint32_t WTX_timer;
bool WTX_process(int read_timeout);
void WTX_clear()
{
WTX_sent = false;
WTX_fail = false;
WTX_timer = 0;
}
bool WTX_on(int WTX_time)
{
WTX_clear();
WTX_timer = millis();
return true;
}
bool WTX_off()
{
WTX_timer = 0;
// read data if we sent WTX
if (WTX_sent)
{
if (!WTX_process(100))
{
printf1(TAG_NFC, "WTX-off get last WTX error\n");
return false;
}
}
if (WTX_fail)
{
printf1(TAG_NFC, "WTX-off fail\n");
return false;
}
WTX_clear();
return true;
}
void WTX_timer_exec()
{
// condition: (timer on) or (not expired[300ms])
if ((WTX_timer <= 0) || WTX_timer + 300 > millis())
return;
WTX_process(10);
WTX_timer = millis();
}
// executes twice a period. 1st for send WTX, 2nd for check the result
// read timeout must be 10 ms to call from interrupt
bool WTX_process(int read_timeout)
{
uint8_t wtx[] = {0xf2, 0x01};
if (WTX_fail)
return false;
if (!WTX_sent)
{
nfc_write_frame(wtx, sizeof(wtx));
WTX_sent = true;
return true;
}
else
{
uint8_t data[32];
int len;
if (!ams_receive_with_timeout(read_timeout, data, sizeof(data), &len))
{
WTX_fail = true;
return false;
}
if (len != 2 || data[0] != 0xf2 || data[1] != 0x01)
{
WTX_fail = true;
return false;
}
WTX_sent = false;
return true;
}
}
int answer_rats(uint8_t parameter)
{
uint8_t fsdi = (parameter & 0xf0) >> 4;
uint8_t cid = (parameter & 0x0f);
NFC_STATE.cid = cid;
if (fsdi == 0)
NFC_STATE.max_frame_size = 16;
else if (fsdi == 1)
NFC_STATE.max_frame_size = 24;
else
NFC_STATE.max_frame_size = 32;
uint8_t res[3 + 11];
res[0] = sizeof(res);
res[1] = 2 | (1<<5); // 2 FSCI == 32 byte frame size, TB is enabled
// frame wait time = (256 * 16 / 13.56MHz) * 2^FWI
// FWI=0, FMT=0.3ms (min)
// FWI=4, FMT=4.8ms (default)
// FWI=10, FMT=309ms
// FWI=12, FMT=1237ms
// FWI=14, FMT=4949ms (max)
res[2] = (12<<4) | (0); // TB (FWI << 4) | (SGTI)
// historical bytes
memcpy(&res[3], (uint8_t *)"SoloKey tap", 11);
nfc_write_frame(res, sizeof(res));
ams_wait_for_tx(10);
return 0;
}
void rblock_acknowledge()
{
uint8_t buf[32];
NFC_STATE.block_num = !NFC_STATE.block_num;
buf[0] = NFC_CMD_RBLOCK | NFC_STATE.block_num;
nfc_write_frame(buf,1);
}
// Selects application. Returns 1 if success, 0 otherwise
int select_applet(uint8_t * aid, int len)
{
if (memcmp(aid,AID_FIDO,sizeof(AID_FIDO)) == 0)
{
NFC_STATE.selected_applet = APP_FIDO;
return APP_FIDO;
}
else if (memcmp(aid,AID_NDEF_TYPE_4,sizeof(AID_NDEF_TYPE_4)) == 0)
{
NFC_STATE.selected_applet = APP_NDEF_TYPE_4;
return APP_NDEF_TYPE_4;
}
else if (memcmp(aid,AID_CAPABILITY_CONTAINER,sizeof(AID_CAPABILITY_CONTAINER)) == 0)
{
NFC_STATE.selected_applet = APP_CAPABILITY_CONTAINER;
return APP_CAPABILITY_CONTAINER;
}
else if (memcmp(aid,AID_NDEF_TAG,sizeof(AID_NDEF_TAG)) == 0)
{
NFC_STATE.selected_applet = APP_NDEF_TAG;
return APP_NDEF_TAG;
}
return APP_NOTHING;
}
void nfc_process_iblock(uint8_t * buf, int len)
{
APDU_HEADER * apdu = (APDU_HEADER *)(buf + 1);
uint8_t * payload = buf + 1 + 5;
uint8_t plen = apdu->lc;
int selected;
CTAP_RESPONSE ctap_resp;
int status;
printf1(TAG_NFC,"Iblock: ");
dump_hex1(TAG_NFC, buf, len);
// TODO this needs to be organized better
switch(apdu->ins)
{
case APDU_INS_SELECT:
if (plen > len - 6)
{
printf1(TAG_ERR, "Truncating APDU length %d\r\n", apdu->lc);
plen = len-6;
}
// if (apdu->p1 == 0 && apdu->p2 == 0x0c)
// {
// printf1(TAG_NFC,"Select NDEF\r\n");
//
// NFC_STATE.selected_applet = APP_NDEF_TAG;
// // Select NDEF file!
// res[0] = NFC_CMD_IBLOCK | (buf[0] & 1);
// res[1] = SW_SUCCESS>>8;
// res[2] = SW_SUCCESS & 0xff;
// nfc_write_frame(res, 3);
// printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3);
// }
// else
{
selected = select_applet(payload, plen);
if (selected == APP_FIDO)
{
// block = buf[0] & 1;
// block = NFC_STATE.block_num;
// block = !block;
// NFC_STATE.block_num = block;
// NFC_STATE.block_num = block;
nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS);
printf1(TAG_NFC, "FIDO applet selected.\r\n");
}
else if (selected != APP_NOTHING)
{
nfc_write_response(buf[0], SW_SUCCESS);
printf1(TAG_NFC, "SELECTED %d\r\n", selected);
}
else
{
nfc_write_response(buf[0], SW_FILE_NOT_FOUND);
printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC,payload, plen);
}
}
break;
case APDU_FIDO_U2F_VERSION:
if (NFC_STATE.selected_applet != APP_FIDO) {
nfc_write_response(buf[0], SW_INS_INVALID);
break;
}
printf1(TAG_NFC, "U2F GetVersion command.\r\n");
nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS);
break;
case APDU_FIDO_U2F_REGISTER:
if (NFC_STATE.selected_applet != APP_FIDO) {
nfc_write_response(buf[0], SW_INS_INVALID);
break;
}
printf1(TAG_NFC, "U2F Register command.\r\n");
if (plen != 64)
{
printf1(TAG_NFC, "U2F Register request length error. len=%d.\r\n", plen);
nfc_write_response(buf[0], SW_WRONG_LENGTH);
return;
}
timestamp();
// WTX_on(WTX_TIME_DEFAULT);
// SystemClock_Config_LF32();
// delay(300);
device_set_clock_rate(DEVICE_LOW_POWER_FAST);;
u2f_request_nfc(&buf[1], len, &ctap_resp);
device_set_clock_rate(DEVICE_LOW_POWER_IDLE);;
// if (!WTX_off())
// return;
printf1(TAG_NFC,"U2F Register P2 took %d\r\n", timestamp());
nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length);
// printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length);
printf1(TAG_NFC,"U2F Register answered %d (took %d)\r\n", millis(), timestamp());
break;
case APDU_FIDO_U2F_AUTHENTICATE:
if (NFC_STATE.selected_applet != APP_FIDO) {
nfc_write_response(buf[0], SW_INS_INVALID);
break;
}
printf1(TAG_NFC, "U2F Authenticate command.\r\n");
if (plen != 64 + 1 + buf[6 + 64])
{
delay(5);
printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", plen, buf[6 + 64]);
nfc_write_response(buf[0], SW_WRONG_LENGTH);
return;
}
timestamp();
// WTX_on(WTX_TIME_DEFAULT);
u2f_request_nfc(&buf[1], len, &ctap_resp);
// if (!WTX_off())
// return;
printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length);
printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), timestamp());
nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length);
printf1(TAG_NFC,"U2F Authenticate answered %d (took %d)\r\n", millis(), timestamp);
break;
case APDU_FIDO_NFCCTAP_MSG:
if (NFC_STATE.selected_applet != APP_FIDO) {
nfc_write_response(buf[0], SW_INS_INVALID);
break;
}
printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", timestamp());
WTX_on(WTX_TIME_DEFAULT);
ctap_response_init(&ctap_resp);
status = ctap_request(payload, plen, &ctap_resp);
if (!WTX_off())
return;
printf1(TAG_NFC, "CTAP resp: 0x%02<30> len: %d\r\n", status, ctap_resp.length);
if (status == CTAP1_ERR_SUCCESS)
{
memmove(&ctap_resp.data[1], &ctap_resp.data[0], ctap_resp.length);
ctap_resp.length += 3;
} else {
ctap_resp.length = 3;
}
ctap_resp.data[0] = status;
ctap_resp.data[ctap_resp.length - 2] = SW_SUCCESS >> 8;
ctap_resp.data[ctap_resp.length - 1] = SW_SUCCESS & 0xff;
printf1(TAG_NFC,"CTAP processing %d (took %d)\r\n", millis(), timestamp());
nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length);
printf1(TAG_NFC,"CTAP answered %d (took %d)\r\n", millis(), timestamp());
break;
case APDU_INS_READ_BINARY:
switch(NFC_STATE.selected_applet)
{
case APP_CAPABILITY_CONTAINER:
printf1(TAG_NFC,"APP_CAPABILITY_CONTAINER\r\n");
if (plen > 15)
{
printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc);
plen = 15;
}
nfc_write_response_ex(buf[0], (uint8_t *)&NFC_CC, plen, SW_SUCCESS);
ams_wait_for_tx(10);
break;
case APP_NDEF_TAG:
printf1(TAG_NFC,"APP_NDEF_TAG\r\n");
if (plen > (sizeof(NDEF_SAMPLE) - 1))
{
printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc);
plen = sizeof(NDEF_SAMPLE) - 1;
}
nfc_write_response_ex(buf[0], NDEF_SAMPLE, plen, SW_SUCCESS);
ams_wait_for_tx(10);
break;
default:
printf1(TAG_ERR, "No binary applet selected!\r\n");
return;
break;
}
break;
default:
printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu->ins);
nfc_write_response(buf[0], SW_INS_INVALID);
break;
}
}
static uint8_t ibuf[1024];
static int ibuflen = 0;
void clear_ibuf()
{
ibuflen = 0;
memset(ibuf, 0, sizeof(ibuf));
}
void nfc_process_block(uint8_t * buf, unsigned int len)
{
if (!len)
return;
if (IS_PPSS_CMD(buf[0]))
{
printf1(TAG_NFC, "NFC_CMD_PPSS\r\n");
}
else if (IS_IBLOCK(buf[0]))
{
if (buf[0] & 0x10)
{
printf1(TAG_NFC_APDU, "NFC_CMD_IBLOCK chaining blen=%d len=%d\r\n", ibuflen, len);
if (ibuflen + len > sizeof(ibuf))
{
printf1(TAG_NFC, "I block memory error! must have %d but have only %d\r\n", ibuflen + len, sizeof(ibuf));
nfc_write_response(buf[0], SW_INTERNAL_EXCEPTION);
return;
}
printf1(TAG_NFC_APDU,"i> ");
dump_hex1(TAG_NFC_APDU, buf, len);
if (len)
{
memcpy(&ibuf[ibuflen], &buf[1], len - 1);
ibuflen += len - 1;
}
// send R block
uint8_t rb = NFC_CMD_RBLOCK | NFC_CMD_RBLOCK_ACK | (buf[0] & 3);
nfc_write_frame(&rb, 1);
} else {
if (ibuflen)
{
if (len)
{
memcpy(&ibuf[ibuflen], &buf[1], len - 1);
ibuflen += len - 1;
}
memmove(&ibuf[1], ibuf, ibuflen);
ibuf[0] = buf[0];
ibuflen++;
printf1(TAG_NFC_APDU, "NFC_CMD_IBLOCK chaining last block. blen=%d len=%d\r\n", ibuflen, len);
printf1(TAG_NFC_APDU,"i> ");
dump_hex1(TAG_NFC_APDU, buf, len);
nfc_process_iblock(ibuf, ibuflen);
} else {
// printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n");
nfc_process_iblock(buf, len);
}
clear_ibuf();
}
}
else if (IS_RBLOCK(buf[0]))
{
rblock_acknowledge();
printf1(TAG_NFC, "NFC_CMD_RBLOCK\r\n");
}
else if (IS_SBLOCK(buf[0]))
{
if ((buf[0] & NFC_SBLOCK_DESELECT) == 0)
{
printf1(TAG_NFC, "NFC_CMD_SBLOCK, DESELECTED\r\n");
nfc_write_frame(buf, 1);
ams_wait_for_tx(2);
ams_write_command(AMS_CMD_SLEEP);
nfc_state_init();
clear_ibuf();
WTX_clear();
}
else
{
printf1(TAG_NFC, "NFC_CMD_SBLOCK, Unknown. len[%d]\r\n", len);
}
dump_hex1(TAG_NFC, buf, len);
}
else
{
printf1(TAG_NFC, "unknown NFC request\r\n len[%d]:", len);
dump_hex1(TAG_NFC, buf, len);
}
}
int nfc_loop()
{
uint8_t buf[32];
AMS_DEVICE ams;
int len = 0;
read_reg_block(&ams);
uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status;
if (state != AMS_STATE_SELECTED && state != AMS_STATE_SELECTEDX)
{
// delay(1); // sleep ?
return 0;
}
if (ams.regs.rfid_status)
{
// if (state != AMS_STATE_SENSE)
// printf1(TAG_NFC," %s x%02x\r\n", ams_get_state_string(ams.regs.rfid_status), state);
}
if (ams.regs.int0 & AMS_INT_INIT)
{
nfc_state_init();
}
if (ams.regs.int1)
{
// ams_print_int1(ams.regs.int1);
}
if ((ams.regs.int0 & AMS_INT_RXE))
{
if (ams.regs.buffer_status2)
{
if (ams.regs.buffer_status2 & AMS_BUF_INVALID)
{
printf1(TAG_NFC,"Buffer being updated!\r\n");
}
else
{
len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK;
ams_read_buffer(buf, len);
}
}
}
if (len)
{
// ISO 14443-3
switch(buf[0])
{
case NFC_CMD_REQA:
printf1(TAG_NFC, "NFC_CMD_REQA\r\n");
break;
case NFC_CMD_WUPA:
printf1(TAG_NFC, "NFC_CMD_WUPA\r\n");
break;
case NFC_CMD_HLTA:
printf1(TAG_NFC, "HLTA/Halt\r\n");
break;
case NFC_CMD_RATS:
answer_rats(buf[1]);
NFC_STATE.block_num = 1;
clear_ibuf();
WTX_clear();
break;
default:
// ISO 14443-4
nfc_process_block(buf,len);
break;
}
}
return len;
}

View File

@ -1,64 +0,0 @@
#ifndef _NFC_H_
#define _NFC_H_
#include <stdint.h>
#include <stdbool.h>
#include "apdu.h"
// Return number of bytes read if any.
int nfc_loop();
bool nfc_init();
typedef struct
{
uint8_t cclen_hi;
uint8_t cclen_lo;
uint8_t version;
uint8_t MLe_hi;
uint8_t MLe_lo;
uint8_t MLc_hi;
uint8_t MLc_lo;
uint8_t tlv[8];
} __attribute__((packed)) CAPABILITY_CONTAINER;
// WTX time in ms
#define WTX_TIME_DEFAULT 300
#define NFC_CMD_REQA 0x26
#define NFC_CMD_WUPA 0x52
#define NFC_CMD_HLTA 0x50
#define NFC_CMD_RATS 0xe0
#define NFC_CMD_PPSS 0xd0
#define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS)
#define NFC_CMD_IBLOCK 0x00
#define IS_IBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_IBLOCK) && (((x) & 0x02) == 0x02) )
#define NFC_CMD_RBLOCK 0x80
#define NFC_CMD_RBLOCK_ACK 0x20
#define IS_RBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_RBLOCK) && (((x) & 0x02) == 0x02) )
#define NFC_CMD_SBLOCK 0xc0
#define IS_SBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_SBLOCK) && (((x) & 0x02) == 0x02) )
#define NFC_SBLOCK_DESELECT 0x30
#define NFC_SBLOCK_WTX 0x30
#define AID_NDEF_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x01"
#define AID_NDEF_MIFARE_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x00"
#define AID_CAPABILITY_CONTAINER "\xE1\x03"
#define AID_NDEF_TAG "\xE1\x04"
#define AID_FIDO "\xa0\x00\x00\x06\x47\x2f\x00\x01"
typedef enum
{
APP_NOTHING = 0,
APP_NDEF_TYPE_4 = 1,
APP_MIFARE_TYPE_4,
APP_CAPABILITY_CONTAINER,
APP_NDEF_TAG,
APP_FIDO,
} APPLETS;
void WTX_timer_exec();
#endif

View File

@ -24,33 +24,19 @@ void _putchar(char c)
} }
int _write (int fd, const void *buf, unsigned long int len)
int _write (int fd, const void *buf, long int len)
{ {
uint8_t * data = (uint8_t *) buf; uint8_t * data = (uint8_t *) buf;
#if DEBUG_LEVEL>1
// static uint8_t logbuf[1000] = {0};
// static int logbuflen = 0;
// if (logbuflen + len > sizeof(logbuf)) {
// int mlen = logbuflen + len - sizeof(logbuf);
// memmove(logbuf, &logbuf[mlen], sizeof(logbuf) - mlen);
// logbuflen -= mlen;
// }
// memcpy(&logbuf[logbuflen], data, len);
// logbuflen += len;
// Send out USB serial // Send out USB serial
CDC_Transmit_FS(buf, len); CDC_Transmit_FS(data, len);
// if (res == USBD_OK)
// logbuflen = 0;
#endif
#ifdef ENABLE_SERIAL_PRINTING
// Send out UART serial // Send out UART serial
while(len--) while(len--)
{ {
_putchar(*data++); _putchar(*data++);
} }
#endif
return 0; return 0;
} }
#endif #endif

View File

@ -7,7 +7,7 @@
* - Set the initial SP * - Set the initial SP
* - Set the initial PC == Reset_Handler, * - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address, * - Set the vector table entries with the exceptions ISR address,
* - Configure the clock system * - Configure the clock system
* - Branches to main in the C library (which eventually * - Branches to main in the C library (which eventually
* calls main()). * calls main()).
* After Reset the Cortex-M4 processor is in Thread mode, * After Reset the Cortex-M4 processor is in Thread mode,
@ -79,8 +79,6 @@ 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
@ -108,7 +106,8 @@ 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.*/
@ -116,7 +115,7 @@ LoopFillZerobss:
LoopForever: LoopForever:
b LoopForever b LoopForever
.size Reset_Handler, .-Reset_Handler .size Reset_Handler, .-Reset_Handler
/** /**
@ -415,49 +414,49 @@ g_pfnVectors:
.weak COMP_IRQHandler .weak COMP_IRQHandler
.thumb_set COMP_IRQHandler,Default_Handler .thumb_set COMP_IRQHandler,Default_Handler
.weak LPTIM1_IRQHandler .weak LPTIM1_IRQHandler
.thumb_set LPTIM1_IRQHandler,Default_Handler .thumb_set LPTIM1_IRQHandler,Default_Handler
.weak LPTIM2_IRQHandler .weak LPTIM2_IRQHandler
.thumb_set LPTIM2_IRQHandler,Default_Handler .thumb_set LPTIM2_IRQHandler,Default_Handler
.weak USB_IRQHandler .weak USB_IRQHandler
.thumb_set USB_IRQHandler,Default_Handler .thumb_set USB_IRQHandler,Default_Handler
.weak DMA2_Channel6_IRQHandler .weak DMA2_Channel6_IRQHandler
.thumb_set DMA2_Channel6_IRQHandler,Default_Handler .thumb_set DMA2_Channel6_IRQHandler,Default_Handler
.weak DMA2_Channel7_IRQHandler .weak DMA2_Channel7_IRQHandler
.thumb_set DMA2_Channel7_IRQHandler,Default_Handler .thumb_set DMA2_Channel7_IRQHandler,Default_Handler
.weak LPUART1_IRQHandler .weak LPUART1_IRQHandler
.thumb_set LPUART1_IRQHandler,Default_Handler .thumb_set LPUART1_IRQHandler,Default_Handler
.weak QUADSPI_IRQHandler .weak QUADSPI_IRQHandler
.thumb_set QUADSPI_IRQHandler,Default_Handler .thumb_set QUADSPI_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler .weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler .thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler .weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler .thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak SAI1_IRQHandler .weak SAI1_IRQHandler
.thumb_set SAI1_IRQHandler,Default_Handler .thumb_set SAI1_IRQHandler,Default_Handler
.weak SWPMI1_IRQHandler .weak SWPMI1_IRQHandler
.thumb_set SWPMI1_IRQHandler,Default_Handler .thumb_set SWPMI1_IRQHandler,Default_Handler
.weak TSC_IRQHandler .weak TSC_IRQHandler
.thumb_set TSC_IRQHandler,Default_Handler .thumb_set TSC_IRQHandler,Default_Handler
.weak RNG_IRQHandler .weak RNG_IRQHandler
.thumb_set RNG_IRQHandler,Default_Handler .thumb_set RNG_IRQHandler,Default_Handler
.weak FPU_IRQHandler .weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler .thumb_set FPU_IRQHandler,Default_Handler
.weak CRS_IRQHandler .weak CRS_IRQHandler
.thumb_set CRS_IRQHandler,Default_Handler .thumb_set CRS_IRQHandler,Default_Handler
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -106,8 +106,6 @@
*/ */
#include "stm32l4xx.h" #include "stm32l4xx.h"
#include "device.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 */
@ -221,9 +219,6 @@ void SystemInit(void)
/* Disable all interrupts */ /* Disable all interrupts */
RCC->CIER = 0x00000000U; RCC->CIER = 0x00000000U;
// TODO this is causing boot issues for old bootloader
device_set_clock_rate(DEVICE_LOW_POWER_IDLE);
} }
/** /**

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,5 @@ ecdsa
fido2 fido2
intelhex intelhex
pyserial pyserial
solo-python
pyusb pyusb
wheel wheel

1085
tools/solotool.py Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
#!/bin/bash
./main
while [ $? == 100 ] ; do
echo "Restarting software authentictor."
./main
done

View File

@ -1,19 +0,0 @@
# 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 bootloader + firmware access
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess"
# ST DFU access
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", TAG+="uaccess"
# U2F Zero
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess"

View File

@ -1,19 +0,0 @@
# 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 bootloader + firmware access
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", MODE="0660", GROUP="plugdev"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", MODE="0660", GROUP="plugdev"
# ST DFU access
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE="0660", GROUP="plugdev"
# U2F Zero
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", MODE="0660", GROUP="plugdev"

View File

@ -1,17 +0,0 @@
# TODO: would like to lookup ID_SERIAL_SHORT from `usb` SUBSYSTEM
# but link on `hidraw` subsystem level
# and end up with symlinks `/dev/solo[hacker|secure]-<serial>`
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", SYMLINK+="solo-$env{ID_SERIAL_SHORT}-%n"
## Solo Secure symlinks
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo [1-9]*", SYMLINK+="solosecure-$env{ID_SERIAL_SHORT}-%n"
## Solo Hacker symlinks
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", ATTRS{product}=="Solo Hacker [1-9]*", SYMLINK+="solohacker-$env{ID_SERIAL_SHORT}-%n"
## Solo Serial access + symlink
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", SYMLINK+="soloserial"
# Non-unique rules (breakdown if multiple Solos are plugged in)
## Solo
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", SYMLINK+="solo"
## U2F Zero
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", SYMLINK+="u2fzero"

View File

@ -1,28 +0,0 @@
# On modern systems, udev has a TAG uaccess, which is used in 73-seat-late.rules
# On older systems, we use GROUP plugdev with MODE
# --> Try `make setup` first, if it doesn't work, try `make legacy-setup`.
#
# The symlinks are optional, install with `make symlinks`.
#
# We keep 99-solo.rules in the parent directory but deprecate it,
# remove when documentation is updated.
setup: install activate
legacy-setup: install-legacy activate
# symlinks: install-symlinks activate
RULES_PATH=/etc/udev/rules.d
activate:
sudo udevadm control --reload-rules
sudo udevadm trigger
install:
sudo ln -sf $(PWD)/70-solokeys-access.rules ${RULES_PATH}/70-solokeys-access.rules
install-legacy:
sudo ln -sf $(PWD)/70-solokeys-legacy-access.rules ${RULES_PATH}/70-solokeys-access.rules
# install-symlinks:
# sudo cp $(PWD)/71-solokeys-symlinks.rules ${RULES_PATH}/71-solokeys-symlinks.rules