Compare commits

...

15 Commits

5 changed files with 300 additions and 196 deletions

View File

@ -32,7 +32,7 @@ Source code 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
- installation python enviroment with command `make venv` from root directory of source code
## Compilation

View File

@ -66,7 +66,7 @@ Environment: Fedora 29 x64, Linux 4.19.9
See <https://docs.solokeys.io/solo/building/> for the original guide. Here details not included there will be covered.
### Install ARM tools
### Install ARM tools Linux
1. Download current [ARM tools] package: [gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2].
@ -75,6 +75,13 @@ See <https://docs.solokeys.io/solo/building/> for the original guide. Here detai
3. Add full path to the `./bin` directory as first entry to the `$PATH` variable,
as in `~/gcc-arm/gcc-arm-none-eabi-8-2018-q4-major/bin/:$PATH`.
### Install ARM tools OsX using brew package manager
```bash
brew tap ArmMbed/homebrew-formulae
brew install arm-none-eabi-gcc
```
### Install flashing software
ST provides a CLI flashing tool - `STM32_Programmer_CLI`. It can be downloaded directly from the vendor's site:
@ -114,8 +121,8 @@ Do not use it, if you do not plan to do so.
```bash
# while in the main project directory
# create Python virtual environment with required packages, and activate
make env3
. env3/bin/activate
make venv
. venv/bin/activate
# Run flashing
cd ./targets/stm32l432
make flash
@ -178,8 +185,8 @@ make fido2-test
#### FIDO2 test sites
1. <https://webauthn.bin.coffee/>
2. <https://github.com/apowers313/fido2-server-demo/>
1. <https://www.passwordless.dev/overview>
2. <https://webauthn.bin.coffee/>
3. <https://webauthn.org/>
#### U2F test sites

View File

@ -26,16 +26,18 @@ static uint8_t *USBD_Composite_GetOtherSpeedCfgDesc (uint16_t *length);
static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);
#define NUM_INTERFACES 2
#define NUM_CLASSES 2
#define NUM_INTERFACES 3
#if NUM_INTERFACES>1
#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (90)
#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (90 + 8+9 + 4)
#else
#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (41)
#endif
#define HID_INTF_NUM 0
#define CDC_INTF_NUM 1
#define CDC_MASTER_INTF_NUM 1
#define CDC_SLAVE_INTF_NUM 2
__ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_SIZE] __ALIGN_END =
{
/*Configuration Descriptor*/
@ -43,7 +45,7 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
COMPOSITE_CDC_HID_DESCRIPTOR_SIZE, /* wTotalLength:no of returned bytes */
0x00,
NUM_INTERFACES, /* bNumInterfaces: 1 interface */
NUM_INTERFACES, /* bNumInterfaces */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0x80, /* bmAttributes: self powered */
@ -92,22 +94,28 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
0x00,
HID_BINTERVAL, /*bInterval: Polling Interval */
#if NUM_INTERFACES > 1
/* */
/* CDC */
/* */
// This "IAD" is needed for Windows since it ignores the standard Union Functional Descriptor
0x08, // bLength
0x0B, // IAD type
CDC_MASTER_INTF_NUM, // First interface
CDC_SLAVE_INTF_NUM, // Next interface
0x02, // bInterfaceClass of the first interface
0x02, // bInterfaceSubClass of the first interface
0x00, // bInterfaceProtocol of the first interface
0x00, // Interface string index
/*Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
/*!*/ CDC_INTF_NUM, /* bInterfaceNumber: Number of Interface */
/*!*/ CDC_MASTER_INTF_NUM, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints: 3 endpoints used */
0x01, /* bNumEndpoints: 1 endpoint used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x00, /* bInterfaceProtocol: Common AT commands */
@ -125,7 +133,7 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
/*!*/ CDC_INTF_NUM, /* bDataInterface: 0 */
/*!*/ CDC_SLAVE_INTF_NUM, /* bDataInterface: 0 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
@ -137,10 +145,10 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
/*!*/ CDC_INTF_NUM, /* bMasterInterface: Communication class interface */
/*!*/ CDC_INTF_NUM, /* bSlaveInterface0: Data Class Interface */
/*!*/ CDC_MASTER_INTF_NUM, /* bMasterInterface: Communication class interface */
/*!*/ CDC_SLAVE_INTF_NUM, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
/* Control Endpoint Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
@ -149,6 +157,17 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
HIBYTE(CDC_CMD_PACKET_SIZE),
0x10, /* bInterval: */
/* Interface descriptor */
0x09, /* bLength */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType */
CDC_SLAVE_INTF_NUM, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0A, /* bInterfaceClass: Communication class data */
0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */
0x00,
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
@ -167,10 +186,13 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
4, /* Descriptor size */
3, /* Descriptor type */
0x09,
0x04,
#endif
};
USBD_ClassTypeDef USBD_Composite =
{
USBD_Composite_Init,
@ -195,14 +217,27 @@ int in_endpoint_to_class[MAX_ENDPOINTS];
int out_endpoint_to_class[MAX_ENDPOINTS];
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *class0, USBD_ClassTypeDef *class1) {
USBD_Classes[0] = class0;
USBD_Classes[1] = class1;
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *hid_class, USBD_ClassTypeDef *cdc_class) {
USBD_Classes[0] = hid_class;
USBD_Classes[1] = cdc_class;
}
static USBD_ClassTypeDef * getClass(uint8_t index)
{
switch(index)
{
case HID_INTF_NUM:
return USBD_Classes[0];
case CDC_MASTER_INTF_NUM:
case CDC_SLAVE_INTF_NUM:
return USBD_Classes[1];
}
return NULL;
}
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
int i;
for(i = 0; i < NUM_INTERFACES; i++) {
for(i = 0; i < NUM_CLASSES; i++) {
if (USBD_Classes[i]->Init(pdev, cfgidx) != USBD_OK) {
return USBD_FAIL;
}
@ -213,7 +248,7 @@ static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
int i;
for(i = 0; i < NUM_INTERFACES; i++) {
for(i = 0; i < NUM_CLASSES; i++) {
if (USBD_Classes[i]->DeInit(pdev, cfgidx) != USBD_OK) {
return USBD_FAIL;
}
@ -224,10 +259,13 @@ static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) {
int i;
USBD_ClassTypeDef * device_class;
device_class = getClass(req->wIndex);
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
case USB_REQ_TYPE_CLASS :
if (req->wIndex < NUM_INTERFACES)
return USBD_Classes[req->wIndex]->Setup(pdev, req);
if (device_class != NULL)
return device_class->Setup(pdev, req);
else
return USBD_FAIL;
@ -236,7 +274,7 @@ static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqType
switch (req->bRequest) {
case USB_REQ_GET_DESCRIPTOR :
for(i = 0; i < NUM_INTERFACES; i++) {
for(i = 0; i < NUM_CLASSES; i++) {
if (USBD_Classes[i]->Setup(pdev, req) != USBD_OK) {
return USBD_FAIL;
}
@ -246,8 +284,8 @@ static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqType
case USB_REQ_GET_INTERFACE :
case USB_REQ_SET_INTERFACE :
if (req->wIndex < NUM_INTERFACES)
return USBD_Classes[req->wIndex]->Setup(pdev, req);
if (device_class != NULL)
return device_class->Setup(pdev, req);
else
return USBD_FAIL;
}
@ -274,7 +312,7 @@ static uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
static uint8_t USBD_Composite_EP0_RxReady (USBD_HandleTypeDef *pdev) {
int i;
for(i = 0; i < NUM_INTERFACES; i++) {
for(i = 0; i < NUM_CLASSES; i++) {
if (USBD_Classes[i]->EP0_RxReady != NULL) {
if (USBD_Classes[i]->EP0_RxReady(pdev) != USBD_OK) {
return USBD_FAIL;

View File

@ -39,6 +39,7 @@ void wait_for_usb_tether();
uint32_t __90_ms = 0;
uint32_t __last_button_press_time = 0;
uint32_t __last_button_bounce_time = 0;
uint32_t __device_status = 0;
uint32_t __last_update = 0;
extern PCD_HandleTypeDef hpcd;
@ -76,6 +77,21 @@ void TIM6_DAC_IRQHandler()
ctaphid_update_status(__device_status);
}
}
if (is_touch_button_pressed == IS_BUTTON_PRESSED)
{
if (IS_BUTTON_PRESSED())
{
// Only allow 1 press per 25 ms.
if ((millis() - __last_button_bounce_time) > 25)
{
__last_button_press_time = millis();
}
__last_button_bounce_time = millis();
}
}
#ifndef IS_BOOTLOADER
// NFC sending WTX if needs
if (device_is_nfc() == NFC_IS_ACTIVE)
@ -84,11 +100,21 @@ void TIM6_DAC_IRQHandler()
}
#endif
}
// Interrupt on rising edge of button (button released)
void EXTI0_IRQHandler(void)
{
EXTI->PR1 = EXTI->PR1;
if (is_physical_button_pressed == IS_BUTTON_PRESSED)
{
// Only allow 1 press per 25 ms.
if ((millis() - __last_button_bounce_time) > 25)
{
__last_button_press_time = millis();
}
__last_button_bounce_time = millis();
}
}
// Global USB interrupt handler
void USB_IRQHandler(void)
@ -499,6 +525,41 @@ static int handle_packets()
return 0;
}
static int wait_for_button_activate(uint32_t wait)
{
int ret;
uint32_t start = millis();
do
{
if ((start + wait) < millis())
{
return 0;
}
delay(1);
ret = handle_packets();
if (ret)
return ret;
} while (!IS_BUTTON_PRESSED());
return 0;
}
static int wait_for_button_release(uint32_t wait)
{
int ret;
uint32_t start = millis();
do
{
if ((start + wait) < millis())
{
return 0;
}
delay(1);
ret = handle_packets();
if (ret)
return ret;
} while (IS_BUTTON_PRESSED());
return 0;
}
int ctap_user_presence_test(uint32_t up_delay)
{
int ret;
@ -506,12 +567,7 @@ int ctap_user_presence_test(uint32_t up_delay)
{
return 1;
}
// "cache" button presses for 2 seconds.
if (millis() - __last_button_press_time < 2000)
{
__last_button_press_time = 0;
return 1;
}
#if SKIP_BUTTON_CHECK_WITH_DELAY
int i=500;
while(i--)
@ -524,53 +580,41 @@ int ctap_user_presence_test(uint32_t up_delay)
#elif SKIP_BUTTON_CHECK_FAST
delay(2);
ret = handle_packets();
if (ret) return ret;
if (ret)
return ret;
goto done;
#endif
uint32_t t1 = millis();
// If button was pressed within last [2] seconds, succeed.
if (__last_button_press_time && (millis() - __last_button_press_time < 2000))
{
goto done;
}
// Set LED status and wait.
led_rgb(0xff3520);
if (IS_BUTTON_PRESSED == is_touch_button_pressed)
{
// Wait for user to release touch button if it's already pressed
while (IS_BUTTON_PRESSED())
{
if (t1 + up_delay < millis())
{
printf1(TAG_GEN,"Button not pressed\n");
goto fail;
}
ret = handle_packets();
// Block and wait for some time.
ret = wait_for_button_activate(up_delay);
if (ret) return ret;
}
}
t1 = millis();
do
{
if (t1 + up_delay < millis())
{
goto fail;
}
delay(1);
ret = handle_packets();
ret = wait_for_button_release(up_delay);
if (ret) return ret;
// If button was pressed within last [2] seconds, succeed.
if (__last_button_press_time && (millis() - __last_button_press_time < 2000))
{
goto done;
}
while (! IS_BUTTON_PRESSED());
led_rgb(0x001040);
delay(50);
#if SKIP_BUTTON_CHECK_WITH_DELAY || SKIP_BUTTON_CHECK_FAST
return 0;
done:
#endif
ret = wait_for_button_release(up_delay);
__last_button_press_time = 0;
return 1;
fail:
return 0;
}
int ctap_generate_rng(uint8_t * dst, size_t num)

View File

@ -92,19 +92,27 @@ int nfc_init()
return NFC_IS_NA;
}
static uint8_t gl_int0 = 0;
void process_int0(uint8_t int0)
{
gl_int0 = int0;
}
bool ams_wait_for_tx(uint32_t timeout_ms)
{
if (gl_int0 & AMS_INT_TXE) {
uint8_t int0 = ams_read_reg(AMS_REG_INT0);
process_int0(int0);
return true;
}
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)
process_int0(int0);
if (int0 & AMS_INT_TXE || int0 & AMS_INT_RXE)
return true;
delay(1);
@ -121,8 +129,13 @@ bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, i
uint32_t tstart = millis();
while (tstart + timeout_ms > millis())
{
uint8_t int0 = ams_read_reg(AMS_REG_INT0);
if (int0) process_int0(int0);
uint8_t int0 = 0;
if (gl_int0 & AMS_INT_RXE) {
int0 = gl_int0;
} else {
int0 = ams_read_reg(AMS_REG_INT0);
process_int0(int0);
}
uint8_t buffer_status2 = ams_read_reg(AMS_REG_BUF2);
if (buffer_status2 && (int0 & AMS_INT_RXE))
@ -196,7 +209,6 @@ bool nfc_write_response(uint8_t req0, uint16_t 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 & 0x0f);
uint8_t block_offset = p14443_block_offset(req0);
@ -208,6 +220,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len)
memcpy(&res[block_offset], data, len);
nfc_write_frame(res, len + block_offset);
} else {
int sendlen = 0;
do {
// transmit I block
int vlen = MIN(32 - block_offset, len - sendlen);
@ -227,11 +240,11 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len)
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 (!ams_wait_for_tx(5))
{
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)
@ -316,7 +329,7 @@ bool WTX_off()
void WTX_timer_exec()
{
// condition: (timer on) or (not expired[300ms])
if ((WTX_timer <= 0) || WTX_timer + 300 > millis())
if ((WTX_timer == 0) || WTX_timer + 300 > millis())
return;
WTX_process(10);
@ -327,12 +340,12 @@ void WTX_timer_exec()
// 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)
{
uint8_t wtx[] = {0xf2, 0x01};
nfc_write_frame(wtx, sizeof(wtx));
WTX_sent = true;
return true;
@ -618,7 +631,7 @@ void nfc_process_iblock(uint8_t * buf, int len)
if (!WTX_off())
return;
printf1(TAG_NFC, "CTAP resp: 0x%02<EFBFBD> len: %d\r\n", status, ctap_resp.length);
printf1(TAG_NFC, "CTAP resp: 0x%02x len: %d\r\n", status, ctap_resp.length);
if (status == CTAP1_ERR_SUCCESS)
{
@ -779,6 +792,8 @@ int nfc_loop()
read_reg_block(&ams);
uint8_t old_int0 = gl_int0;
process_int0(ams.regs.int0);
uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status;
if (state != AMS_STATE_SELECTED && state != AMS_STATE_SELECTEDX)
@ -792,7 +807,7 @@ int nfc_loop()
// 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)
if (ams.regs.int0 & AMS_INT_INIT || old_int0 & AMS_INT_INIT)
{
nfc_state_init();
}
@ -801,7 +816,7 @@ int nfc_loop()
// ams_print_int1(ams.regs.int1);
}
if ((ams.regs.int0 & AMS_INT_RXE))
if (ams.regs.int0 & AMS_INT_RXE || old_int0 & AMS_INT_RXE)
{
if (ams.regs.buffer_status2)
{