Compare commits

..

2 Commits

Author SHA1 Message Date
f1c406ab9c fail with more import info 2019-07-08 21:48:39 -04:00
1185574d21 default no serial printing 2019-07-08 21:48:22 -04:00
8 changed files with 20 additions and 102 deletions

View File

@ -1 +1 @@
2.4.0
2.3.0

View File

@ -1,40 +1,22 @@
# Building solo
To build, develop and debug the firmware for the STM32L432. This will work
for Solo Hacker, the Nucleo development board, or your own homemade Solo.
There exists a development board [NUCLEO-L432KC](https://www.st.com/en/evaluation-tools/nucleo-l432kc.html) you can use; The board does contain a debugger, so all you need is a USB cable (and some [udev](/udev) [rules](https://rust-embedded.github.io/book/intro/install/linux.html#udev-rules)).
## Prerequisites
# Prerequisites
Install the [latest ARM compiler toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) for your system. We recommend getting the latest compilers from ARM.
You can also install the ARM toolchain using a package manager like `apt-get` or `pacman`,
but be warned they might be out of date. Typically it will be called `gcc-arm-none-eabi binutils-arm-none-eabi`.
Install `solo-python` usually with `pip3 install solo-python`. The `solo` python application may also be used for [programming](#programming).
To program your build, you'll need one of the following programs.
- [openocd](http://openocd.org)
- [stlink](https://github.com/texane/stlink)
- [STM32CubeProg](https://www.st.com/en/development-tools/stm32cubeprog.html)
- [openocd](http://openocd.org)
- [stlink](https://github.com/texane/stlink)
- [STM32CubeProg](https://www.st.com/en/development-tools/stm32cubeprog.html)
## Obtain source code and solo tool
Source code can be downloaded from:
- [github releases list](https://github.com/solokeys/solo/releases)
- [github repository](https://github.com/solokeys/solo)
**solo** tool can be downloaded from:
- from python programs [repository](https://pypi.org/project/solo-python/) `pip install solo-python`
- from installing prerequisites `pip3 install -r tools/requirements.txt`
- github repository: [repository](https://github.com/solokeys/solo-python)
- installation python enviroment witn command `make venv` from root directory of source code
## Compilation
# Compilation
Enter the `stm32l4xx` target directory.
@ -98,7 +80,8 @@ make build-release-locked
Programming `all.hex` will cause the device to permanently lock itself.
## Programming
# Programming
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!).
@ -112,7 +95,7 @@ pip3 install -r tools/requirements.txt
If you're on Windows, you must also install [libusb](https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/).
### Pre-programmed Solo Hacker
## Pre-programmed Solo Hacker
If your Solo device is already programmed (it flashes green when powered), we recommend
programming it using the Solo bootloader.
@ -135,7 +118,7 @@ If something bad happens, you can always boot the Solo bootloader by doing the f
If you hold the button for an additional 5 seconds, it will boot to the ST DFU (device firmware update).
Don't use the ST DFU unless you know what you're doing.
### ST USB DFU
## ST USB DFU
If your Solo has never been programmed, it will boot the ST USB DFU. The LED is turned
off and it enumerates as "STM BOOTLOADER".
@ -153,7 +136,7 @@ Make sure to program `all.hex`, as this contains both the bootloader and the Sol
If all goes well, you should see a slow-flashing green light.
### Solo Hacker vs Solo
## Solo Hacker vs Solo
A Solo hacker device doesn't need to be in bootloader mode to be programmed, it will automatically switch.
@ -161,7 +144,7 @@ Solo (locked) needs the button to be held down when plugged in to boot to the bo
A locked Solo will only accept signed updates.
### Signed updates
## Signed updates
If this is not a device with a hacker build, you can only program signed updates.
@ -179,7 +162,7 @@ solo sign /path/to/signing-key.pem /path/to/solo.hex /output-path/to/firmware.js
If your Solo isn't locked, you can always reprogram it using a debugger connected directly
to the token.
## Permanently locking the device
# Permanently locking the device
If you plan to be using your Solo for real, you should lock it permanently. This prevents
someone from connecting a debugger to your token and stealing credentials.

View File

@ -38,7 +38,6 @@ void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, ui
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey);
void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret);
#define CRYPTO_TRANSPORT_KEY2 ((uint8_t*)2)
#define CRYPTO_TRANSPORT_KEY ((uint8_t*)1)
#define CRYPTO_MASTER_KEY ((uint8_t*)0)

View File

@ -355,9 +355,9 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf
}
// Generate credRandom
crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY2, 0, credRandom);
crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY, 0, credRandom);
crypto_sha256_update((uint8_t*)&ext->hmac_secret.credential->id, sizeof(CredentialId));
crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY2, 0, credRandom);
crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY, 0, credRandom);
// Decrypt saltEnc
crypto_aes256_init(shared_secret, NULL);
@ -605,6 +605,7 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa
crypto_sha256_final(hashbuf);
crypto_ecc256_sign(hashbuf, 32, sigbuf);
return ctap_encode_der_sig(sigbuf,sigder);
}
@ -1055,7 +1056,7 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
else
#endif
{
sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_buf_sz, clientDataHash, auth_data_buf, sigbuf, sigder);
sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
}
{

View File

@ -157,11 +157,6 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
key = master_secret;
klen = sizeof(master_secret)/2;
}
else if (key == CRYPTO_TRANSPORT_KEY2)
{
key = transport_secret;
klen = 32;
}
if(klen > 64)

View File

@ -211,7 +211,7 @@ class FIDO2Tests(Tester):
assert "hmac-secret" in reg.auth_data.extensions
assert reg.auth_data.extensions["hmac-secret"] == True
self.testMC(
reg = self.testMC(
"Send MC with fake extension set to true, expect SUCCESS",
cdh,
rp,
@ -278,10 +278,6 @@ class FIDO2Tests(Tester):
assert shannon_entropy(ext["hmac-secret"]) > 5.4
assert shannon_entropy(key) > 5.4
with Test("Check that the assertion is valid"):
credential_data = AttestedCredentialData(reg.auth_data.credential_data)
auth.verify(cdh, credential_data.public_key)
salt_enc, salt_auth = get_salt_params((salt3,))
auth = self.testGA(
@ -747,40 +743,6 @@ class FIDO2Tests(Tester):
expectedError=CtapError.ERR.SUCCESS,
)
with Test("Check assertion is correct"):
credential_data = AttestedCredentialData(prev_reg.auth_data.credential_data)
prev_auth.verify(cdh, credential_data.public_key)
assert (
prev_auth.credential["id"]
== prev_reg.auth_data.credential_data.credential_id
)
self.reboot()
prev_auth = self.testGA(
"Send GA request after reboot, expect success",
rp["id"],
cdh,
allow_list,
expectedError=CtapError.ERR.SUCCESS,
)
with Test("Check assertion is correct"):
credential_data = AttestedCredentialData(prev_reg.auth_data.credential_data)
prev_auth.verify(cdh, credential_data.public_key)
assert (
prev_auth.credential["id"]
== prev_reg.auth_data.credential_data.credential_id
)
prev_auth = self.testGA(
"Send GA request, expect success",
rp["id"],
cdh,
allow_list,
expectedError=CtapError.ERR.SUCCESS,
)
with Test("Test auth_data is 37 bytes"):
assert len(prev_auth.auth_data) == 37

View File

@ -1,8 +1,7 @@
import time, struct
from fido2.pcsc import CtapPcscDevice
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client
from fido2.attestation import Attestation
from fido2.ctap1 import CTAP1
from fido2.utils import Timeout
@ -202,18 +201,7 @@ class Tester:
self.ctap.reset()
def testMC(self, test, *args, **kwargs):
attestation_object = self.testFunc(
self.ctap.make_credential, test, *args, **kwargs
)
if attestation_object:
verifier = Attestation.for_type(attestation_object.fmt)
client_data = args[0]
verifier().verify(
attestation_object.att_statement,
attestation_object.auth_data,
client_data,
)
return attestation_object
return self.testFunc(self.ctap.make_credential, test, *args, **kwargs)
def testGA(self, test, *args, **kwargs):
return self.testFunc(self.ctap.get_assertion, test, *args, **kwargs)

View File

@ -78,16 +78,6 @@ class U2FTests(Tester):
auth = self.authenticate(chal, appid, regs[i].key_handle)
auth.verify(appid, chal, regs[i].public_key)
self.reboot()
for i in range(0, self.user_count):
with Test(
"Post reboot, Checking previous registration %d/%d"
% (i + 1, self.user_count)
):
auth = self.authenticate(chal, appid, regs[i].key_handle)
auth.verify(appid, chal, regs[i].public_key)
print("Check that all previous credentials are registered...")
for i in range(0, self.user_count):
with Test("Check that previous credential %d is registered" % i):