commit
ed6da0ba1e
@ -10,9 +10,12 @@ LABEL="mm_usb_device_blacklist_end"
|
||||
|
||||
# Solo
|
||||
|
||||
## access
|
||||
## 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
|
||||
|
@ -28,5 +28,4 @@ RUN ln -s /opt/conda/bin/python3 /usr/local/bin/python3
|
||||
RUN ln -s /opt/conda/bin/python3 /usr/local/bin/python
|
||||
|
||||
# 3. Source code
|
||||
RUN git clone --recurse-submodules https://github.com/solokeys/solo /solo
|
||||
|
||||
RUN git clone --recurse-submodules https://github.com/solokeys/solo /solo --config core.autocrlf=input
|
||||
|
6
Makefile
6
Makefile
@ -75,10 +75,12 @@ fido2-test: venv
|
||||
venv/bin/python tools/ctap_test.py
|
||||
|
||||
DOCKER_IMAGE := "solokeys/solo-firmware:local"
|
||||
SOLO_VERSION := "master"
|
||||
SOLO_VERSIONISH := "master"
|
||||
docker-build:
|
||||
docker build -t $(DOCKER_IMAGE) .
|
||||
docker run --rm -v$(PWD)/builds:/builds -v$(PWD)/docker-build.sh:/build.sh $(DOCKER_IMAGE) /build.sh $(SOLO_VERSION)
|
||||
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
||||
-v "$(CURDIR)/in-docker-build.sh:/in-docker-build.sh" \
|
||||
$(DOCKER_IMAGE) /in-docker-build.sh $(SOLO_VERSIONISH)
|
||||
|
||||
CPPCHECK_FLAGS=--quiet --error-exitcode=2
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/bin/bash -xe
|
||||
|
||||
version=${1:-master}
|
||||
|
||||
export PREFIX=/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/
|
||||
|
||||
cd /solo/targets/stm32l432
|
||||
git checkout ${version}
|
||||
version=$(git describe)
|
||||
make cbor
|
||||
make all-hacker
|
||||
|
||||
cd /
|
||||
|
||||
out_dir="builds"
|
||||
out_hex="solo-${version}.hex"
|
||||
out_sha2="solo-${version}.sha2"
|
||||
cp /solo/targets/stm32l432/solo.hex ${out_dir}/${out_hex}
|
||||
cd ${out_dir}
|
||||
sha256sum ${out_hex} > ${out_sha2}
|
||||
|
37
fido2/ctap.c
37
fido2/ctap.c
@ -21,6 +21,7 @@
|
||||
#include "device.h"
|
||||
#include APP_CONFIG
|
||||
#include "wallet.h"
|
||||
#include "extensions.h"
|
||||
|
||||
#include "device.h"
|
||||
|
||||
@ -776,8 +777,19 @@ int ctap_filter_invalid_credentials(CTAP_getAssertion * GA)
|
||||
if (! ctap_authenticate_credential(&GA->rp, &GA->creds[i]))
|
||||
{
|
||||
printf1(TAG_GA, "CRED #%d is invalid\n", GA->creds[i].credential.id.count);
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if (is_extension_request((uint8_t*)&GA->creds[i].credential.id, sizeof(CredentialId)))
|
||||
{
|
||||
printf1(TAG_EXT, "CRED #%d is extension\n", GA->creds[i].credential.id.count);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GA->creds[i].credential.id.count = 0; // invalidate
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// add user info if it exists
|
||||
@ -856,6 +868,7 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
|
||||
int ret;
|
||||
uint8_t sigbuf[64];
|
||||
uint8_t sigder[72];
|
||||
int sigder_sz;
|
||||
|
||||
if (add_user)
|
||||
{
|
||||
@ -869,7 +882,16 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
|
||||
|
||||
crypto_ecc256_load_key((uint8_t*)&cred->credential.id, sizeof(CredentialId), NULL, 0);
|
||||
|
||||
int sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if ( extend_fido2(&cred->credential.id, sigder) )
|
||||
{
|
||||
sigder_sz = 72;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(map, RESP_signature);
|
||||
@ -988,8 +1010,21 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
||||
ret = cbor_encoder_create_map(encoder, &map, map_size);
|
||||
check_ret(ret);
|
||||
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if ( is_extension_request((uint8_t*)&GA.creds[validCredCount - 1].credential.id, sizeof(CredentialId)) )
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_authData);
|
||||
check_ret(ret);
|
||||
memset(auth_data_buf,0,sizeof(auth_data_buf));
|
||||
ret = cbor_encode_byte_string(&map, auth_data_buf, sizeof(auth_data_buf));
|
||||
check_ret(ret);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0);
|
||||
check_retr(ret);
|
||||
}
|
||||
|
||||
/*for (int j = 0; j < GA.credLen; j++)*/
|
||||
/*{*/
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdint.h>
|
||||
#include "extensions.h"
|
||||
#include "u2f.h"
|
||||
#include "ctap.h"
|
||||
#include "wallet.h"
|
||||
#include "solo.h"
|
||||
#include "device.h"
|
||||
@ -57,7 +58,8 @@ int16_t bridge_u2f_to_extensions(uint8_t * _chal, uint8_t * _appid, uint8_t klen
|
||||
#elif defined(WALLET_EXTENSION)
|
||||
ret = bridge_u2f_to_wallet(_chal, _appid, klen, keyh);
|
||||
#else
|
||||
ret = bridge_u2f_to_solo(_chal, _appid, klen, keyh);
|
||||
ret = bridge_u2f_to_solo(sig, keyh, klen);
|
||||
u2f_response_writeback(sig,72);
|
||||
#endif
|
||||
|
||||
if (ret != 0)
|
||||
@ -74,6 +76,21 @@ int16_t bridge_u2f_to_extensions(uint8_t * _chal, uint8_t * _appid, uint8_t klen
|
||||
return U2F_SW_NO_ERROR;
|
||||
}
|
||||
|
||||
// Returns 1 if this is a extension request.
|
||||
// Else 0 if nothing is done.
|
||||
int16_t extend_fido2(CredentialId * credid, uint8_t * output)
|
||||
{
|
||||
if (is_extension_request((uint8_t*)credid, sizeof(CredentialId)))
|
||||
{
|
||||
output[0] = bridge_u2f_to_solo(output+1, (uint8_t*)credid, sizeof(CredentialId));
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
|
||||
{
|
||||
|
||||
@ -93,7 +110,7 @@ int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
|
||||
{
|
||||
rcode = U2F_SW_WRONG_DATA;
|
||||
}
|
||||
printf1(TAG_EXT,"Ignoring U2F request\n");
|
||||
printf1(TAG_EXT,"Ignoring U2F check request\n");
|
||||
dump_hex1(TAG_EXT, (uint8_t *) &auth->kh, auth->khl);
|
||||
goto end;
|
||||
}
|
||||
@ -102,7 +119,7 @@ int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
|
||||
if ( ! is_extension_request((uint8_t *) &auth->kh, auth->khl)) // Pin requests
|
||||
{
|
||||
rcode = U2F_SW_WRONG_PAYLOAD;
|
||||
printf1(TAG_EXT, "Ignoring U2F request\n");
|
||||
printf1(TAG_EXT, "Ignoring U2F auth request\n");
|
||||
dump_hex1(TAG_EXT, (uint8_t *) &auth->kh, auth->khl);
|
||||
goto end;
|
||||
}
|
||||
|
@ -10,6 +10,10 @@
|
||||
|
||||
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len);
|
||||
|
||||
int16_t extend_fido2(CredentialId * credid, uint8_t * output);
|
||||
|
||||
int bootloader_bridge(int klen, uint8_t * keyh);
|
||||
|
||||
int is_extension_request(uint8_t * kh, int len);
|
||||
|
||||
#endif /* EXTENSIONS_H_ */
|
||||
|
@ -31,27 +31,26 @@
|
||||
#include "log.h"
|
||||
#include APP_CONFIG
|
||||
|
||||
int16_t bridge_u2f_to_solo(uint8_t * _chal, uint8_t * _appid, uint8_t klen, uint8_t * keyh)
|
||||
// output must be at least 71 bytes
|
||||
int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen)
|
||||
{
|
||||
static uint8_t msg_buf[72];
|
||||
int8_t ret = 0;
|
||||
|
||||
wallet_request * req = (wallet_request *) keyh;
|
||||
|
||||
printf1(TAG_WALLET, "u2f-solo [%d]: ", klen); dump_hex1(TAG_WALLET, keyh, klen);
|
||||
printf1(TAG_WALLET, "u2f-solo [%d]: ", keylen); dump_hex1(TAG_WALLET, keyh, keylen);
|
||||
|
||||
switch(req->operation)
|
||||
{
|
||||
case WalletVersion:
|
||||
msg_buf[0] = SOLO_VERSION_MAJ;
|
||||
msg_buf[1] = SOLO_VERSION_MIN;
|
||||
msg_buf[2] = SOLO_VERSION_PATCH;
|
||||
u2f_response_writeback(msg_buf, 3);
|
||||
output[0] = SOLO_VERSION_MAJ;
|
||||
output[1] = SOLO_VERSION_MIN;
|
||||
output[2] = SOLO_VERSION_PATCH;
|
||||
break;
|
||||
case WalletRng:
|
||||
printf1(TAG_WALLET,"SoloRng\n");
|
||||
|
||||
ret = ctap_generate_rng(msg_buf, 72);
|
||||
ret = ctap_generate_rng(output, 71);
|
||||
if (ret != 1)
|
||||
{
|
||||
printf1(TAG_WALLET,"Rng failed\n");
|
||||
@ -60,7 +59,6 @@ int16_t bridge_u2f_to_solo(uint8_t * _chal, uint8_t * _appid, uint8_t klen, uint
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
u2f_response_writeback((uint8_t *)msg_buf,72);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -22,6 +22,6 @@
|
||||
#ifndef SOLO_H_
|
||||
#define SOLO_H_
|
||||
|
||||
int16_t bridge_u2f_to_solo(uint8_t * _chal, uint8_t * _appid, uint8_t klen, uint8_t * keyh);
|
||||
int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen);
|
||||
|
||||
#endif
|
||||
|
@ -47,7 +47,7 @@ struct logtag tagtable[] = {
|
||||
{TAG_WALLET,"[1;34mWALLET[0m"},
|
||||
{TAG_STOR,"[1;35mSTOR[0m"},
|
||||
{TAG_BOOT,"[1;36mBOOT[0m"},
|
||||
{TAG_BOOT,"[1;37mEXT[0m"},
|
||||
{TAG_EXT,"[1;37mEXT[0m"},
|
||||
};
|
||||
|
||||
|
||||
|
@ -41,7 +41,7 @@ typedef enum
|
||||
TAG_STOR = (1 << 15),
|
||||
TAG_DUMP2 = (1 << 16),
|
||||
TAG_BOOT = (1 << 17),
|
||||
TAG_EXT = (1 << 17),
|
||||
TAG_EXT = (1 << 18),
|
||||
|
||||
TAG_FILENO = (1u << 31)
|
||||
} LOG_TAG;
|
||||
|
@ -44,7 +44,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
rcode = extend_u2f(req, len);
|
||||
#endif
|
||||
if (rcode != U2F_SW_NO_ERROR) // 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...
|
||||
{
|
||||
#ifdef ENABLE_U2F
|
||||
switch(req->ins)
|
||||
@ -224,7 +224,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
||||
}
|
||||
|
||||
count = ctap_atomic_count(0);
|
||||
hash[0] = (count >> 24) & 0xff;
|
||||
hash[0] = 0xff;
|
||||
hash[1] = (count >> 16) & 0xff;
|
||||
hash[2] = (count >> 8) & 0xff;
|
||||
hash[3] = (count >> 0) & 0xff;
|
||||
@ -241,7 +241,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
||||
crypto_ecc256_sign(hash, 32, sig);
|
||||
|
||||
u2f_response_writeback(&up,1);
|
||||
hash[0] = (count >> 24) & 0xff;
|
||||
hash[0] = 0xff;
|
||||
hash[1] = (count >> 16) & 0xff;
|
||||
hash[2] = (count >> 8) & 0xff;
|
||||
hash[3] = (count >> 0) & 0xff;
|
||||
|
37
in-docker-build.sh
Executable file
37
in-docker-build.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash -xe
|
||||
|
||||
version=${1:-master}
|
||||
|
||||
export PREFIX=/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/
|
||||
|
||||
cd /solo/targets/stm32l432
|
||||
git fetch
|
||||
git checkout ${version}
|
||||
version=$(git describe)
|
||||
|
||||
make cbor
|
||||
|
||||
out_dir="/builds"
|
||||
|
||||
function build() {
|
||||
part=${1}
|
||||
variant=${2}
|
||||
output=${3:-${part}}
|
||||
what="${part}-${variant}"
|
||||
|
||||
make full-clean
|
||||
|
||||
make ${what}
|
||||
|
||||
out_hex="${what}-${version}.hex"
|
||||
out_sha2="${what}-${version}.sha2"
|
||||
|
||||
mv ${output}.hex ${out_hex}
|
||||
sha256sum ${out_hex} > ${out_sha2}
|
||||
cp ${out_hex} ${out_sha2} ${out_dir}
|
||||
}
|
||||
|
||||
build bootloader nonverifying
|
||||
build bootloader verifying
|
||||
build firmware hacker solo
|
||||
build firmware secure solo
|
@ -9,6 +9,25 @@ 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
|
||||
|
||||
|
||||
# The following are the main targets for reproducible builds.
|
||||
# TODO: better explanation
|
||||
firmware-hacker:
|
||||
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0'
|
||||
|
||||
firmware-secure:
|
||||
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DUSE_SOLOKEYS_CERT -DFLASH_ROP=2'
|
||||
|
||||
bootloader-nonverifying:
|
||||
$(MAKE) -f $(BOOTMAKE) -j8 bootloader.hex PREFIX=$(PREFIX) EXTRA_DEFINES='-DSOLO_HACKER' DEBUG=0
|
||||
|
||||
bootloader-verifying:
|
||||
$(MAKE) -f $(BOOTMAKE) -j8 bootloader.hex PREFIX=$(PREFIX) DEBUG=0
|
||||
|
||||
full-clean: clean2
|
||||
|
||||
|
||||
# The older targets, may be re-organised
|
||||
all:
|
||||
$(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DFLASH_ROP=1'
|
||||
|
||||
|
@ -4,7 +4,7 @@ include build/common.mk
|
||||
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 += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||
SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c)
|
||||
SRC += $(DRIVER_LIBS) $(USB_LIB)
|
||||
|
||||
# FIDO2 lib
|
||||
SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c
|
||||
|
@ -5,7 +5,7 @@ SRC = bootloader/main.c bootloader/bootloader.c
|
||||
SRC += src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
|
||||
SRC += src/fifo.c src/crypto.c src/attestation.c
|
||||
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||
SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c)
|
||||
SRC += $(DRIVER_LIBS) $(USB_LIB)
|
||||
|
||||
# FIDO2 lib
|
||||
SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/extensions/extensions.c
|
||||
|
@ -3,6 +3,15 @@ CP=$(PREFIX)arm-none-eabi-objcopy
|
||||
SZ=$(PREFIX)arm-none-eabi-size
|
||||
AR=$(PREFIX)arm-none-eabi-ar
|
||||
|
||||
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_usb.c lib/stm32l4xx_ll_utils.c lib/stm32l4xx_ll_pwr.c \
|
||||
lib/stm32l4xx_ll_usart.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_ctlreq.c lib/usbd/usbd_desc.c lib/usbd/usbd_hid.c
|
||||
|
||||
VERSION:=$(shell git describe --abbrev=0 )
|
||||
VERSION_FULL:=$(shell git describe)
|
||||
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
|
||||
@ -10,7 +19,7 @@ VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
|
||||
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
|
||||
|
||||
VERSION_FLAGS= -DSOLO_VERSION_MAJ=$(VERSION_MAJ) -DSOLO_VERSION_MIN=$(VERSION_MIN) \
|
||||
-DSOLO_VERSION_PATCH=$(VERSION_PAT) -DVERSION=\"$(VERSION_FULL)\"
|
||||
-DSOLO_VERSION_PATCH=$(VERSION_PAT) -DSOLO_VERSION=\"$(VERSION_FULL)\"
|
||||
|
||||
_all:
|
||||
echo $(VERSION_FULL)
|
||||
|
@ -166,6 +166,32 @@ uint8_t *USBD_HID_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *l
|
||||
*/
|
||||
uint8_t *USBD_HID_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_SERIAL_NUM, USBD_StrDesc, length);
|
||||
// Match the same alg as the DFU to make serial number
|
||||
volatile uint8_t * UUID = (volatile uint8_t *)0x1FFF7590;
|
||||
const char hexdigit[] = "0123456789ABCDEF";
|
||||
uint8_t uuid[6];
|
||||
uint8_t uuid_str[13];
|
||||
uint8_t c;
|
||||
int i;
|
||||
uuid_str[12] = 0;
|
||||
|
||||
uuid[0] = UUID[11];
|
||||
uuid[1] = UUID[10] + UUID[2];
|
||||
uuid[2] = UUID[9];
|
||||
uuid[3] = UUID[8] + UUID[0];
|
||||
uuid[4] = UUID[7];
|
||||
uuid[5] = UUID[6];
|
||||
|
||||
// quick method to convert to hex string
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
c = (uuid[i]>>4) & 0x0f;
|
||||
uuid_str[i * 2 + 0] = hexdigit[ c ];
|
||||
c = (uuid[i]>>0) & 0x0f;
|
||||
uuid_str[i * 2 + 1] = hexdigit[ c ];
|
||||
}
|
||||
|
||||
|
||||
USBD_GetString((uint8_t *)uuid_str, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
@ -383,12 +383,16 @@ class Tester:
|
||||
def test_u2f(self,):
|
||||
chal = sha256(b"AAA")
|
||||
appid = sha256(b"BBB")
|
||||
lastc = 0
|
||||
for i in range(0, 5):
|
||||
reg = self.ctap1.register(chal, appid)
|
||||
reg.verify(appid, chal)
|
||||
auth = self.ctap1.authenticate(chal, appid, reg.key_handle)
|
||||
# check endianness
|
||||
assert auth.counter < 0x10000
|
||||
if lastc:
|
||||
assert (auth.counter - lastc) < 10
|
||||
lastc = auth.counter
|
||||
print(hex(lastc))
|
||||
print("U2F reg + auth pass %d/5" % (i + 1))
|
||||
|
||||
def test_fido2_simple(self, pin_token=None):
|
||||
|
@ -201,6 +201,24 @@ class SoloClient:
|
||||
|
||||
return res.signature[1:]
|
||||
|
||||
def exchange_fido2(self, cmd, addr=0, data=b"A" * 16):
|
||||
chal = "B" * 32
|
||||
|
||||
req = SoloClient.format_request(cmd, addr, data)
|
||||
|
||||
assertions, client_data = self.client.get_assertion(
|
||||
self.host, chal, [{"id": req, "type": "public-key"}]
|
||||
)
|
||||
if len(assertions) < 1:
|
||||
raise RuntimeError("Device didn't respond to FIDO2 extended assertion")
|
||||
|
||||
res = assertions[0]
|
||||
ret = res.signature[0]
|
||||
if ret != CtapError.ERR.SUCCESS:
|
||||
raise RuntimeError("Device returned non-success code %02x" % (ret,))
|
||||
|
||||
return res.signature[1:]
|
||||
|
||||
def bootloader_version(self,):
|
||||
data = self.exchange(SoloBootloader.version)
|
||||
if len(data) > 2:
|
||||
@ -208,7 +226,7 @@ class SoloClient:
|
||||
return data[0]
|
||||
|
||||
def solo_version(self,):
|
||||
data = self.exchange_u2f(SoloExtension.version)
|
||||
data = self.exchange_fido2(SoloExtension.version)
|
||||
return (data[0], data[1], data[2])
|
||||
|
||||
def write_flash(self, addr, data):
|
||||
@ -585,6 +603,7 @@ def solo_main():
|
||||
action="store_true",
|
||||
help="Continuously dump random numbers generated from Solo.",
|
||||
)
|
||||
|
||||
parser.add_argument("--wink", action="store_true", help="HID Wink command.")
|
||||
parser.add_argument(
|
||||
"--reset",
|
||||
@ -596,6 +615,9 @@ def solo_main():
|
||||
action="store_true",
|
||||
help="Verify that the Solo firmware is from SoloKeys. Check firmware version.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--version", action="store_true", help="Check firmware version on Solo."
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
p = SoloClient()
|
||||
@ -627,6 +649,9 @@ def solo_main():
|
||||
else:
|
||||
print("Unknown fingerprint! ", cert.fingerprint(hashes.SHA256()))
|
||||
|
||||
args.version = True
|
||||
|
||||
if args.version:
|
||||
try:
|
||||
v = p.solo_version()
|
||||
print("Version: ", v)
|
||||
|
Loading…
x
Reference in New Issue
Block a user