From a0e0e78551d2f65c40f0517312136fbfe46b39c9 Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Wed, 24 Oct 2018 22:03:31 -0700 Subject: [PATCH 01/26] Fix undefined behavior I run cppcheck :) Shifting *signed* 32-bit value by 31 bits is undefined behaviour. --- targets/stm32l442/src/flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l442/src/flash.c b/targets/stm32l442/src/flash.c index 500d6ad..092a6f5 100644 --- a/targets/stm32l442/src/flash.c +++ b/targets/stm32l442/src/flash.c @@ -89,5 +89,5 @@ void flash_write(uint32_t addr, uint8_t * data, size_t sz) void flash_lock() { - FLASH->CR |= (1<<31); + FLASH->CR |= (1U<<31); } From 2819c0a21521ad9ca46f17909b058b0444cbe494 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 21:23:44 -0400 Subject: [PATCH 02/26] Update targets/stm32l442/lib/usbd/usbd_conf.c fix some issues with usb configuration --- targets/stm32l442/lib/usbd/usbd_conf.c | 69 +++++++++++++------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/targets/stm32l442/lib/usbd/usbd_conf.c b/targets/stm32l442/lib/usbd/usbd_conf.c index 87dabca..43f8c69 100644 --- a/targets/stm32l442/lib/usbd/usbd_conf.c +++ b/targets/stm32l442/lib/usbd/usbd_conf.c @@ -64,23 +64,19 @@ PCD_HandleTypeDef hpcd; */ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); + if(hpcd->Init.low_power_enable == 1) + { + /* Enable EXTI Line 17 for USB wakeup */ + __HAL_USB_WAKEUP_EXTI_ENABLE_IT(); + } - /*LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);*/ - // SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); - // - // if(hpcd->Init.low_power_enable == 1) - // { - // /* Enable EXTI Line 17 for USB wakeup */ - // __HAL_USB_WAKEUP_EXTI_ENABLE_IT(); - // } - // - // /*[> Set USB FS Interrupt priority <]*/ - // /*HAL_NVIC_SetPriority(USB_IRQn, 0x0F, 0);*/ - // NVIC_SetPriority(USB_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x0f, 0)); - // - // /*[> Enable USB FS Interrupt <]*/ - // NVIC_EnableIRQ(USB_IRQn); + /* Set USB FS Interrupt priority */ + NVIC_SetPriority(USB_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x0f, 0)); + + /* Enable USB FS Interrupt */ + NVIC_EnableIRQ(USB_IRQn); } /** @@ -223,35 +219,38 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData); } -/******************************************************************************* - LL Driver Interface (USB Device Library --> PCD) -*******************************************************************************/ - /** - * @brief Initializes the Low Level portion of the Device driver. + * @brief Initializes the low level portion of the device driver. * @param pdev: Device handle - * @retval USBD Status + * @retval USBD status */ + extern void _Error_Handler(char *file, int line); USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) { - /* Set LL Driver parameters */ - hpcd.Instance = USB; - hpcd.Init.dev_endpoints = 8; - hpcd.Init.ep0_mps = 0x40; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.speed = PCD_SPEED_FULL; - hpcd.Init.low_power_enable = 1; - /* Link The driver to the stack */ + /* Enable USB power on Pwrctrl CR2 register. */ + SET_BIT(PWR->CR2, PWR_CR2_USV); + /* Link the driver to the stack. */ hpcd.pData = pdev; pdev->pData = &hpcd; - /* Initialize LL Driver */ - HAL_PCD_Init(&hpcd); - - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x18); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x58); - HAL_PCDEx_PMAConfig(&hpcd , 0x81 , PCD_SNG_BUF, 0x100); + hpcd.Instance = USB; + hpcd.Init.dev_endpoints = 8; + hpcd.Init.speed = PCD_SPEED_FULL; + hpcd.Init.ep0_mps = DEP0CTL_MPS_64; + hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd.Init.Sof_enable = DISABLE; + hpcd.Init.low_power_enable = DISABLE; + hpcd.Init.lpm_enable = DISABLE; + hpcd.Init.battery_charging_enable = DISABLE; + if (HAL_PCD_Init(&hpcd) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x98); + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xd8); return USBD_OK; } From 705ee2886097c7a6a1d9978a54a7bceea98416d5 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 21:25:49 -0400 Subject: [PATCH 03/26] initial fido2 port --- fido2/device.h | 2 + fido2/main.c | 4 +- pc/device.c | 8 +- targets/stm32l442/Makefile | 44 ++-- targets/stm32l442/lib/usbd_hid.c | 109 +++++----- targets/stm32l442/src/app.h | 22 ++ targets/stm32l442/src/crypto.c | 355 +++++++++++++++++++++++++++++++ targets/stm32l442/src/device.c | 180 +++++++++++++++- targets/stm32l442/src/device.h | 12 -- targets/stm32l442/src/fifo.c | 2 +- targets/stm32l442/src/fifo.h | 2 + targets/stm32l442/src/flash.c | 5 +- targets/stm32l442/src/init.c | 1 + targets/stm32l442/src/main.c | 2 + targets/stm32l442/src/redirect.c | 30 +-- targets/stm32l442/src/rng.c | 5 +- 16 files changed, 659 insertions(+), 124 deletions(-) create mode 100644 targets/stm32l442/src/crypto.c delete mode 100644 targets/stm32l442/src/device.h diff --git a/fido2/device.h b/fido2/device.h index 5f030bb..a49391c 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -53,6 +53,8 @@ int authenticator_is_backup_initialized(); void authenticator_write_state(AuthenticatorState *, int backup); +// Called each main loop. Doesn't need to do anything. +void device_manage(); // Test for user presence // Return 1 for user is present, 0 user not present diff --git a/fido2/main.c b/fido2/main.c index d39147b..a2cca61 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -85,6 +85,8 @@ int main(int argc, char * argv[]) t1 = millis(); } + device_manage(); + if (usbhid_recv(hidmsg) > 0) { printf1(TAG_DUMP,"%d>> ",count++); dump_hex1(TAG_DUMP, hidmsg,sizeof(hidmsg)); @@ -110,5 +112,3 @@ int main(int argc, char * argv[]) } #endif - - diff --git a/pc/device.c b/pc/device.c index 43ad521..348e6e4 100644 --- a/pc/device.c +++ b/pc/device.c @@ -398,7 +398,7 @@ void authenticator_initialize() } } - - - - +void manage_device() +{ + +} diff --git a/targets/stm32l442/Makefile b/targets/stm32l442/Makefile index a3675b2..f4f59d3 100644 --- a/targets/stm32l442/Makefile +++ b/targets/stm32l442/Makefile @@ -1,16 +1,32 @@ CC=arm-none-eabi-gcc CP=arm-none-eabi-objcopy SZ=arm-none-eabi-size +AR=arm-none-eabi-ar +# 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/fifo.c -SRC += ../../fido2/util.c +SRC += src/fifo.c src/crypto.c SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c) +# FIDO2 lib +SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c ../../fido2/test_power.c +SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c +SRC += ../../fido2/ctap_parse.c ../../fido2/main.c + +# Crypto libs +SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c ../../crypto/tiny-AES-c/aes.c + + OBJ1=$(SRC:.c=.o) OBJ=$(OBJ1:.s=.o) -INC=-Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ + +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../../crypto/tiny-AES-c + +SEARCH=-L../../tinycbor/lib + LDSCRIPT=stm32l432xx.ld CFLAGS= $(INC) @@ -23,8 +39,12 @@ HW=-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb # Solo CHIP=STM32L442xx -CFLAGS=$(INC) -c -D$(CHIP) -DUSE_FULL_LL_DRIVER -Os -Wall -fdata-sections -ffunction-sections -LDFLAGS=$(HW) -specs=nano.specs -specs=nosys.specs -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref -Wl,--gc-sections -u _printf_float +DEFINES = -D$(CHIP) -DAES256=1 -DUSE_FULL_LL_DRIVER + +CFLAGS=$(INC) -c $(DEFINES) -Os -Wall -fdata-sections -ffunction-sections $(HW) +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 -ltinycbor + .PRECIOUS: %.o @@ -52,12 +72,8 @@ flash: $(TARGET).hex sleep 0.5 python dfuse-tool/dfuse-tool.py --leave -test: - STM32_Programmer_CLI -c port=SWD -halt -d ../../../cube_stm32l442/build/cube_stm32l442.hex -rst - sleep 0.5 - python dfuse-tool/dfuse-tool.py --leave - -test2: - STM32_Programmer_CLI -c port=SWD -halt -d ../../../stmusb2/build/stmusb2.hex -rst - sleep 0.5 - python dfuse-tool/dfuse-tool.py --leave +cbor: + cd ../../tinycbor/ && make clean + cd ../../tinycbor/ && make CC="$(CC)" AR=$(AR) \ +LDFLAGS="$(LDFLAGS_LIB)" \ +CFLAGS="$(CFLAGS)" diff --git a/targets/stm32l442/lib/usbd_hid.c b/targets/stm32l442/lib/usbd_hid.c index c28d013..0cc9512 100644 --- a/targets/stm32l442/lib/usbd_hid.c +++ b/targets/stm32l442/lib/usbd_hid.c @@ -95,6 +95,9 @@ static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length); static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev, + uint8_t epnum); + USBD_ClassTypeDef USBD_HID = { @@ -104,7 +107,7 @@ USBD_ClassTypeDef USBD_HID = NULL, /*EP0_TxSent*/ NULL, /*EP0_RxReady*/ USBD_HID_DataIn, /*DataIn*/ - NULL, /*DataOut*/ + USBD_HID_DataOut, /*DataOut*/ NULL, /*SOF */ NULL, NULL, @@ -223,8 +226,7 @@ __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_FIDO_REPORT_DESC_SIZE] __ 0x95, HID_PACKET_SIZE, // REPORT_COUNT (64) 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0xc0,// END_COLLECTION + 0xc0,// END_COLLECTION }; @@ -233,12 +235,46 @@ static uint8_t hidmsg_buf[64]; void usb_hid_recieve_callback(uint8_t ep) { fifo_hidmsg_add(hidmsg_buf); + memset(hidmsg_buf,0,64); USBD_LL_PrepareReceive(&Solo_USBD_Device, HID_ENDPOINT, hidmsg_buf, HID_PACKET_SIZE); } +static void dump_pma() +{ + + register uint32_t _wRegBase = (uint32_t)USB; + _wRegBase += (uint32_t)(USB)->BTABLE + 0x400; + + uint16_t * pma_ptr = (uint16_t *)_wRegBase; + uint16_t val; + uint32_t offset = (uint32_t)(USB)->BTABLE; + + printf("btable: %02lx\r\n",offset); + + for (int i = 0; i < 2; i++) + { + uint16_t addr_tx = pma_ptr[i * 4 + 0]; + uint16_t cnt_tx = pma_ptr[i * 4 + 1]; + uint16_t addr_rx = pma_ptr[i * 4 + 2]; + uint16_t cnt_rx = pma_ptr[i * 4 + 3]; + + printf("EP%d addr_tx == %02x, count_tx == %02x\r\n", i, addr_tx,cnt_tx ); + printf("EP%d addr_rx == %02x, count_rx == %02x\r\n", i, addr_rx,cnt_rx ); + } + + uint16_t ep1_tx = pma_ptr[1 * 4 + 0]; + + for (int i = 0; i < 32; i++) + { + val = pma_ptr[ep1_tx + i]; + printf("%04x ",val); + } + printf("\r\n"); +} + /** * @brief USBD_HID_Init * Initialize the HID interface @@ -252,17 +288,12 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) /* Open EP IN */ USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE); USBD_LL_OpenEP(pdev, HID_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_EPOUT_SIZE); - static uint8_t mem[4]; + static uint8_t mem[sizeof (USBD_HID_HandleTypeDef)]; pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U; pdev->ep_out[HID_EPOUT_ADDR & 0xFU].is_used = 1U; pdev->pClassData = mem; - if (pdev->pClassData == NULL) - { - return USBD_FAIL; - } - ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; @@ -411,60 +442,8 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, return ret; } -/** - * @brief USBD_HID_SendReport - * Send HID Report - * @param pdev: device instance - * @param buff: pointer to report - * @retval status - */ -uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, - uint8_t *report, - uint16_t len) -{ - USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData; - if (pdev->dev_state == USBD_STATE_CONFIGURED ) - { - if(hhid->state == HID_IDLE) - { - hhid->state = HID_BUSY; - USBD_LL_Transmit (pdev, - HID_EPIN_ADDR, - report, - len); - } - } - return USBD_OK; -} -/** - * @brief USBD_HID_GetPollingInterval - * return polling interval from endpoint descriptor - * @param pdev: device instance - * @retval polling interval - */ -uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev) -{ - uint32_t polling_interval = 0U; - - /* HIGH-speed endpoints */ - if(pdev->dev_speed == USBD_SPEED_HIGH) - { - /* Sets the data transfer polling interval for high speed transfers. - Values between 1..16 are allowed. Values correspond to interval - of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */ - polling_interval = (((1U <<(HID_BINTERVAL - 1U))) / 8U); - } - else /* LOW and FULL-speed endpoints */ - { - /* Sets the data transfer polling interval for low and full - speed transfers */ - polling_interval = HID_BINTERVAL; - } - - return ((uint32_t)(polling_interval)); -} /** * @brief USBD_HID_GetCfgFSDesc @@ -495,6 +474,14 @@ static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, return USBD_OK; } +static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev, + uint8_t epnum) +{ + /* Ensure that the FIFO is empty before a new transfer, this condition could + be caused by a new transfer before the end of the previous transfer */ + ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; + return USBD_OK; +} /** * @brief DeviceQualifierDescriptor diff --git a/targets/stm32l442/src/app.h b/targets/stm32l442/src/app.h index 6254f66..f17c5b3 100644 --- a/targets/stm32l442/src/app.h +++ b/targets/stm32l442/src/app.h @@ -5,8 +5,30 @@ #define DEBUG_UART USART1 + + +#define DEBUG_LEVEL 1 + +#define NON_BLOCK_PRINTING 1 + +//#define PRINTING_USE_VCOM + +//#define USING_DEV_BOARD + +//#define ENABLE_U2F_EXTENSIONS + +#define ENABLE_U2F + +//#define DISABLE_CTAPHID_PING +//#define DISABLE_CTAPHID_WINK +//#define DISABLE_CTAPHID_CBOR + +void printing_init(); void hw_init(void); +//#define TEST +//#define TEST_POWER +#define LED_INIT_VALUE 0x001000 #endif diff --git a/targets/stm32l442/src/crypto.c b/targets/stm32l442/src/crypto.c new file mode 100644 index 0000000..1a4af35 --- /dev/null +++ b/targets/stm32l442/src/crypto.c @@ -0,0 +1,355 @@ +/* + * Wrapper for crypto implementation on device + * + * */ +#include +#include +#include + + + +#include "util.h" +#include "crypto.h" + +#ifdef USE_SOFTWARE_IMPLEMENTATION + +#include "sha256.h" +#include "uECC.h" +#include "aes.h" +#include "ctap.h" +#include "device.h" +#include "app.h" + + +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, + MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ + MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ + MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ + MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ + MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ + MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ + MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ +} mbedtls_ecp_group_id; + + + +const uint8_t attestation_cert_der[]; +const uint16_t attestation_cert_der_size; +const uint8_t attestation_key[]; +const uint16_t attestation_key_size; + + + +static SHA256_CTX sha256_ctx; +static const struct uECC_Curve_t * _es256_curve = NULL; +static const uint8_t * _signing_key = NULL; +static int _key_len = 0; + +// Secrets for testing only +static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff" + "\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00"; + +static uint8_t transport_secret[32] = "\x10\x01\x22\x33\x44\x55\x66\x77\x87\x90\x0a\xbb\x3c\xd8\xee\xff" + "\xff\xee\x8d\x1c\x3b\xfa\x99\x88\x77\x86\x55\x44\xd3\xff\x33\x00"; + + + +void crypto_sha256_init() +{ + sha256_init(&sha256_ctx); +} + +void crypto_reset_master_secret() +{ + ctap_generate_rng(master_secret, 32); +} + + +void crypto_sha256_update(uint8_t * data, size_t len) +{ + sha256_update(&sha256_ctx, data, len); +} + +void crypto_sha256_update_secret() +{ + sha256_update(&sha256_ctx, master_secret, 32); +} + +void crypto_sha256_final(uint8_t * hash) +{ + sha256_final(&sha256_ctx, hash); +} + +void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac) +{ + uint8_t buf[64]; + int i; + memset(buf, 0, sizeof(buf)); + + if (key == CRYPTO_MASTER_KEY) + { + key = master_secret; + klen = sizeof(master_secret); + } + + if(klen > 64) + { + printf("Error, key size must be <= 64\n"); + exit(1); + } + + memmove(buf, key, klen); + + for (i = 0; i < sizeof(buf); i++) + { + buf[i] = buf[i] ^ 0x36; + } + + crypto_sha256_init(); + crypto_sha256_update(buf, 64); +} + +void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac) +{ + uint8_t buf[64]; + int i; + crypto_sha256_final(hmac); + memset(buf, 0, sizeof(buf)); + if (key == CRYPTO_MASTER_KEY) + { + key = master_secret; + klen = sizeof(master_secret); + } + + + if(klen > 64) + { + printf("Error, key size must be <= 64\n"); + exit(1); + } + memmove(buf, key, klen); + + for (i = 0; i < sizeof(buf); i++) + { + buf[i] = buf[i] ^ 0x5c; + } + + crypto_sha256_init(); + crypto_sha256_update(buf, 64); + crypto_sha256_update(hmac, 32); + crypto_sha256_final(hmac); +} + + +void crypto_ecc256_init() +{ + uECC_set_rng((uECC_RNG_Function)ctap_generate_rng); + _es256_curve = uECC_secp256r1(); +} + + +void crypto_ecc256_load_attestation_key() +{ + _signing_key = attestation_key; + _key_len = 32; +} + +void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig) +{ + if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0) + { + printf("error, uECC failed\n"); + exit(1); + } +} + +void crypto_ecc256_load_key(uint8_t * data, int len, uint8_t * data2, int len2) +{ + static uint8_t privkey[32]; + generate_private_key(data,len,data2,len2,privkey); + _signing_key = privkey; + _key_len = 32; +} + +void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID) +{ + + const struct uECC_Curve_t * curve = NULL; + + switch(MBEDTLS_ECP_ID) + { + case MBEDTLS_ECP_DP_SECP192R1: + curve = uECC_secp192r1(); + if (_key_len != 24) goto fail; + break; + case MBEDTLS_ECP_DP_SECP224R1: + curve = uECC_secp224r1(); + if (_key_len != 28) goto fail; + break; + case MBEDTLS_ECP_DP_SECP256R1: + curve = uECC_secp256r1(); + if (_key_len != 32) goto fail; + break; + case MBEDTLS_ECP_DP_SECP256K1: + curve = uECC_secp256k1(); + if (_key_len != 32) goto fail; + break; + default: + printf("error, invalid ECDSA alg specifier\n"); + exit(1); + } + + if ( uECC_sign(_signing_key, data, len, sig, curve) == 0) + { + printf("error, uECC failed\n"); + exit(1); + } + return; + +fail: + printf("error, invalid key length\n"); + exit(1); + +} + +void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, uint8_t * privkey) +{ + crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey); + crypto_sha256_update(data, len); + crypto_sha256_update(data2, len2); + crypto_sha256_update(master_secret, 32); + crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey); +} + + +/*int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);*/ +void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y) +{ + uint8_t privkey[32]; + uint8_t pubkey[64]; + + generate_private_key(data,len,NULL,0,privkey); + + memset(pubkey,0,sizeof(pubkey)); + uECC_compute_public_key(privkey, pubkey, _es256_curve); + memmove(x,pubkey,32); + memmove(y,pubkey+32,32); +} + +void crypto_load_external_key(uint8_t * key, int len) +{ + _signing_key = key; + _key_len = len; +} + + +void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey) +{ + if (uECC_make_key(pubkey, privkey, _es256_curve) != 1) + { + printf("Error, uECC_make_key failed\n"); + exit(1); + } +} + +void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret) +{ + if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1) + { + printf("Error, uECC_shared_secret failed\n"); + exit(1); + } + +} + +struct AES_ctx aes_ctx; +void crypto_aes256_init(uint8_t * key, uint8_t * nonce) +{ + if (key == CRYPTO_TRANSPORT_KEY) + { + AES_init_ctx(&aes_ctx, transport_secret); + } + else + { + AES_init_ctx(&aes_ctx, key); + } + if (nonce == NULL) + { + memset(aes_ctx.Iv, 0, 16); + } + else + { + memmove(aes_ctx.Iv, nonce, 16); + } +} + +// prevent round key recomputation +void crypto_aes256_reset_iv(uint8_t * nonce) +{ + if (nonce == NULL) + { + memset(aes_ctx.Iv, 0, 16); + } + else + { + memmove(aes_ctx.Iv, nonce, 16); + } +} + +void crypto_aes256_decrypt(uint8_t * buf, int length) +{ + AES_CBC_decrypt_buffer(&aes_ctx, buf, length); +} + +void crypto_aes256_encrypt(uint8_t * buf, int length) +{ + AES_CBC_encrypt_buffer(&aes_ctx, buf, length); +} + + +const uint8_t attestation_cert_der[] = +"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08" +"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" +"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e" +"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38" +"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32" +"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" +"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x0f\x30\x0d" +"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55" +"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20" +"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72" +"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04" +"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07" +"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00" +"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf" +"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83" +"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca" +"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d" +"\xa1\x30\xa4\x2e\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31" +"\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e\x06\x03\x55\x04" +"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94" +"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04" +"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00" +"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e" +"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd" +"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7" +"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7"; + + +const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1; + + +const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30"; +const uint16_t attestation_key_size = sizeof(attestation_key)-1; + + +#else +#error "No crypto implementation defined" +#endif diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 6074230..7afc23f 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -1,25 +1,201 @@ #include "device.h" #include "usbd_def.h" +#include "stm32l4xx.h" +#include "stm32l4xx_ll_tim.h" +#include "stm32l4xx_ll_usart.h" +#include "usbd_hid.h" + +#include "app.h" +#include "flash.h" +#include "rng.h" +#include "led.h" +#include "device.h" +#include "util.h" +#include "fifo.h" +#include "log.h" uint32_t __65_seconds = 0; +extern PCD_HandleTypeDef hpcd; + +// Timer6 overflow handler void TIM6_DAC_IRQHandler() { // timer is only 16 bits, so roll it over here TIM6->SR = 0; __65_seconds += 1; } - -extern PCD_HandleTypeDef hpcd; // Global USB interrupt handler void USB_IRQHandler(void) { HAL_PCD_IRQHandler(&hpcd); } + +uint32_t millis() +{ + return (((uint32_t)TIM6->CNT) | (__65_seconds<<16)); +} + + + + void delay(uint32_t ms) { uint32_t time = millis(); while ((millis() - time) < ms) ; } + +void device_init() +{ + hw_init(); + printf1(TAG_GEN,"hello solo\r\n"); +} + +void usbhid_init() +{ + printf1(TAG_GEN,"hello solo\r\n"); +} +int usbhid_recv(uint8_t * msg) +{ + if (fifo_hidmsg_size()) + { + + fifo_hidmsg_take(msg); + printf1(TAG_DUMP,">> "); + dump_hex1(TAG_DUMP,msg, HID_PACKET_SIZE); + return HID_PACKET_SIZE; + } + return 0; +} + +void usbhid_send(uint8_t * msg) +{ + printf1(TAG_DUMP,"<< "); + dump_hex1(TAG_DUMP, msg, HID_PACKET_SIZE); + // USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)&Solo_USBD_Device.pClassData; + + USBD_LL_Transmit(&Solo_USBD_Device, HID_EPIN_ADDR, msg, HID_PACKET_SIZE); + +} + +void ctaphid_write_block(uint8_t * data) +{ + usbhid_send(data); +} + + +void usbhid_close() +{ + +} + +void main_loop_delay() +{ + +} + +void heartbeat() +{ + static int state = 0; + static uint32_t val = (LED_INIT_VALUE >> 8) & 0xff; + // int but = IS_BUTTON_PRESSED(); + int but = 0; + + if (state) + { + val--; + } + else + { + val++; + } + + if (val > 30 || val < 1) + { + state = !state; + } + // int c = PCD_GET_EP_TX_CNT(USB,1); + // int c = PCD_GET_EP_TX_STATUS(USB,1); + // printf("tx counter: %x\r\n",PCD_GET_EP_TX_CNT(USB,1)); + + // if (but) RGB(val * 2); + // else + led_rgb((val << 16) | (val*2 << 8)); +} + +void authenticator_read_state(AuthenticatorState * a) +{ + +} + +void authenticator_read_backup_state(AuthenticatorState * a) +{ + +} + +// Return 1 yes backup is init'd, else 0 +//void authenticator_initialize() +int authenticator_is_backup_initialized() +{ + return 0; +} + +void authenticator_write_state(AuthenticatorState * a, int backup) +{ + +} + +void device_manage() +{ +#if NON_BLOCK_PRINTING + int i = 10; + uint8_t c; + while (i--) + { + if (fifo_debug_size()) + { + fifo_debug_take(&c); + while (! LL_USART_IsActiveFlag_TXE(DEBUG_UART)) + ; + LL_USART_TransmitData8(DEBUG_UART,c); + } + else + { + break; + } + } +#endif +} + +int ctap_user_presence_test() +{ + return 1; +} + +int ctap_generate_rng(uint8_t * dst, size_t num) +{ + rng_get_bytes(dst, num); + return 1; +} + +uint32_t ctap_atomic_count(int sel) +{ + static uint32_t c = 4; + return c++; +} + +int ctap_user_verification(uint8_t arg) +{ + return 1; +} + + +void _Error_Handler(char *file, int line) +{ + printf2(TAG_ERR,"Error: %s: %d\r\n", file, line); + while(1) + { + } +} diff --git a/targets/stm32l442/src/device.h b/targets/stm32l442/src/device.h deleted file mode 100644 index ee9219a..0000000 --- a/targets/stm32l442/src/device.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _DEVICE_H_ -#define _DEVICE_H_ - -#include -#include "stm32l4xx_ll_tim.h" - -void delay(uint32_t ms); - -#define millis() (((uint32_t)TIM6->CNT) | (__65_seconds<<16)) -extern uint32_t __65_seconds; - -#endif diff --git a/targets/stm32l442/src/fifo.c b/targets/stm32l442/src/fifo.c index 8f1526e..c8f621e 100644 --- a/targets/stm32l442/src/fifo.c +++ b/targets/stm32l442/src/fifo.c @@ -4,7 +4,7 @@ #include "fifo.h" - +FIFO_CREATE(debug,1024,1) FIFO_CREATE(hidmsg,100,100) diff --git a/targets/stm32l442/src/fifo.h b/targets/stm32l442/src/fifo.h index f4c5a6c..31efa95 100644 --- a/targets/stm32l442/src/fifo.h +++ b/targets/stm32l442/src/fifo.h @@ -51,6 +51,8 @@ uint32_t fifo_##NAME##_size();\ FIFO_CREATE_H(hidmsg,10,64) +FIFO_CREATE_H(debug,1024,1) + FIFO_CREATE_H(test,100,100) void fifo_test(); diff --git a/targets/stm32l442/src/flash.c b/targets/stm32l442/src/flash.c index 500d6ad..b86ef87 100644 --- a/targets/stm32l442/src/flash.c +++ b/targets/stm32l442/src/flash.c @@ -5,6 +5,7 @@ #include "app.h" #include "flash.h" +#include "log.h" static void flash_unlock() { @@ -33,7 +34,7 @@ void flash_erase_page(uint8_t page) if(FLASH->SR & (1<<1)) { - printf("erase NOT successful %lx\r\n", FLASH->SR); + printf2(TAG_ERR,"erase NOT successful %lx\r\n", FLASH->SR); } FLASH->CR &= ~(0x7); @@ -58,7 +59,7 @@ void flash_write_dword(uint32_t addr, uint64_t data) if(FLASH->SR & (1<<1)) { - printf("program NOT successful %lx\r\n", FLASH->SR); + printf2(TAG_ERR,"program NOT successful %lx\r\n", FLASH->SR); } FLASH->SR = (1<<0); diff --git a/targets/stm32l442/src/init.c b/targets/stm32l442/src/init.c index e669e91..62d5a19 100644 --- a/targets/stm32l442/src/init.c +++ b/targets/stm32l442/src/init.c @@ -20,6 +20,7 @@ #include "usbd_core.h" #include "usbd_desc.h" #include "usbd_hid.h" +#include "device.h" /* USER CODE BEGIN Includes */ diff --git a/targets/stm32l442/src/main.c b/targets/stm32l442/src/main.c index f6ff5d8..1aef4a3 100644 --- a/targets/stm32l442/src/main.c +++ b/targets/stm32l442/src/main.c @@ -28,6 +28,7 @@ #include "util.h" #include "fifo.h" +#ifdef TEST_SOLO_STM32 #define Error_Handler() _Error_Handler(__FILE__,__LINE__) int main(void) @@ -101,3 +102,4 @@ void _Error_Handler(char *file, int line) { } } +#endif diff --git a/targets/stm32l442/src/redirect.c b/targets/stm32l442/src/redirect.c index 63fe851..0f997d6 100644 --- a/targets/stm32l442/src/redirect.c +++ b/targets/stm32l442/src/redirect.c @@ -1,38 +1,19 @@ #include "stm32l4xx_ll_usart.h" #include "app.h" +#include "fifo.h" -int WRITE_PTR = 0; -int READ_PTR = 0; -#define BUF_SIZE 20000 -static uint8_t WRITE_BUF[BUF_SIZE]; -void add2buf(uint8_t c) -{ - WRITE_BUF[WRITE_PTR++] = c; - if (WRITE_PTR >= BUF_SIZE) - WRITE_PTR = 0; -} -uint8_t takebuf() -{ - uint8_t c; - c = WRITE_BUF[READ_PTR++]; - if (READ_PTR >= BUF_SIZE) - READ_PTR = 0; - return c; -} - -uint8_t bufavail() -{ - return (READ_PTR < WRITE_PTR); -} void _putchar(char c) { - // add2buf(c); +#if NON_BLOCK_PRINTING + fifo_debug_add(&c); +#else while (! LL_USART_IsActiveFlag_TXE(DEBUG_UART)) ; LL_USART_TransmitData8(DEBUG_UART,c); +#endif } int _write (int fd, const void *buf, long int len) @@ -43,4 +24,5 @@ int _write (int fd, const void *buf, long int len) _putchar(*data++); } return 0; + } diff --git a/targets/stm32l442/src/rng.c b/targets/stm32l442/src/rng.c index 526a387..f1027d2 100644 --- a/targets/stm32l442/src/rng.c +++ b/targets/stm32l442/src/rng.c @@ -5,6 +5,7 @@ #include "stm32l4xx_ll_rng.h" #include "rng.h" +#include "log.h" int __errno = 0; @@ -20,7 +21,7 @@ void rng_get_bytes(uint8_t * dst, size_t sz) if (RNG->SR & 0x66) { - printf("Error RNG: %02lx\r\n", RNG->SR); + printf2(TAG_ERR,"Error RNG: %02lx\r\n", RNG->SR); exit(1); } @@ -54,7 +55,7 @@ float shannon_entropy(float * p, size_t sz) return entropy; } -// Measure shannon entropy of RNG +// Measure shannon entropy of RNG float rng_test(size_t n) { unsigned int i; From bdf2a47e7266f11353da8a87b3fc962fd0ff7c25 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 21:33:29 -0400 Subject: [PATCH 04/26] block on usb tx --- targets/stm32l442/src/device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 7afc23f..9b8a12c 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -74,8 +74,8 @@ void usbhid_send(uint8_t * msg) { printf1(TAG_DUMP,"<< "); dump_hex1(TAG_DUMP, msg, HID_PACKET_SIZE); - // USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)&Solo_USBD_Device.pClassData; - + while (PCD_GET_EP_TX_STATUS(USB, HID_EPIN_ADDR & 0x0f) == USB_EP_TX_VALID) + ; USBD_LL_Transmit(&Solo_USBD_Device, HID_EPIN_ADDR, msg, HID_PACKET_SIZE); } From 26920551b2830ed69abb6990b6c66371dd4f8a93 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 21:55:09 -0400 Subject: [PATCH 05/26] re-enable some usbhid tests --- tools/ctap_test.py | 139 +++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/tools/ctap_test.py b/tools/ctap_test.py index 5274438..c80b36d 100644 --- a/tools/ctap_test.py +++ b/tools/ctap_test.py @@ -61,6 +61,7 @@ class Tester(): self.origin = 'https://examplo.org' def find_device(self,): + print (list(CtapHidDevice.list_devices())) dev = next(CtapHidDevice.list_devices(), None) if not dev: raise RuntimeError('No FIDO device found') @@ -118,34 +119,34 @@ class Tester(): def test_long_ping(self): amt = 1000 - while 1 : - pingdata = os.urandom(amt) + pingdata = os.urandom(amt) + try: + t1 = time.time() * 1000 + r = self.send_data(CTAPHID.PING, pingdata) + t2 = time.time() * 1000 + delt = t2 - t1 + #if (delt < 140 ): + #raise RuntimeError('Fob is too fast (%d ms)' % delt) + if (delt > 555 * (amt/1000)): + raise RuntimeError('Fob is too slow (%d ms)' % delt) + if (r != pingdata): + raise ValueError('Ping data not echo\'d') + print('1000 byte ping time: %s ms' % delt) + except CtapError as e: + print('7609 byte Ping failed:', e) + raise RuntimeError('ping failed') + print('PASS: 7609 byte ping') + #sys.flush(sys.sto) + sys.stdout.flush() + + + def test_hid(self,check_timeouts = False): + if check_timeouts: + print('Test idle') try: - t1 = time.time() * 1000 - r = self.send_data(CTAPHID.PING, pingdata) - t2 = time.time() * 1000 - delt = t2 - t1 - #if (delt < 140 ): - #raise RuntimeError('Fob is too fast (%d ms)' % delt) - if (delt > 555 * (amt/1000)): - raise RuntimeError('Fob is too slow (%d ms)' % delt) - if (r != pingdata): - raise ValueError('Ping data not echo\'d') - print('1000 byte ping time: %s ms' % delt) - except CtapError as e: - print('7609 byte Ping failed:', e) - raise RuntimeError('ping failed') - print('PASS: 7609 byte ping') - #sys.flush(sys.sto) - sys.stdout.flush() - - - def test_hid(self,): - #print('Test idle') - #try: - #cmd,resp = self.recv_raw() - #except socket.timeout: - #print('Pass: Idle') + cmd,resp = self.recv_raw() + except socket.timeout: + print('Pass: Idle') print('Test init') r = self.send_data(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11') @@ -216,18 +217,19 @@ class Tester(): self.check_error(resp, CtapError.ERR.INVALID_LENGTH) print('PASS: invalid length') - #r = self.send_data(CTAPHID.PING, '\x44'*200) - #print('Sending packets that skip a sequence number.') - #self.send_raw('\x81\x04\x90') - #self.send_raw('\x00') - #self.send_raw('\x01') - ## skip 2 - #self.send_raw('\x03') - #cmd,resp = self.recv_raw() - #self.check_error(resp, CtapError.ERR.INVALID_SEQ) - #cmd,resp = self.recv_raw() - #assert(cmd == 0xbf) # timeout - #print('PASS: invalid sequence') + r = self.send_data(CTAPHID.PING, '\x44'*200) + print('Sending packets that skip a sequence number.') + self.send_raw('\x81\x04\x90') + self.send_raw('\x00') + self.send_raw('\x01') + # skip 2 + self.send_raw('\x03') + cmd,resp = self.recv_raw() + self.check_error(resp, CtapError.ERR.INVALID_SEQ) + if check_timeouts: + cmd,resp = self.recv_raw() + assert(cmd == 0xbf) # timeout + print('PASS: invalid sequence') print('Resync and send ping') try: @@ -262,13 +264,13 @@ class Tester(): cmd,r = self.recv_raw() # init response assert(cmd == 0x86) self.set_cid(oldcid) - #print('wait for timeout') - #cmd,r = self.recv_raw() # timeout response - #assert(cmd == 0xbf) + if check_timeouts: + #print('wait for timeout') + cmd,r = self.recv_raw() # timeout response + assert(cmd == 0xbf) print('PASS: resync and timeout') - print('Test timeout') self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88') t1 = time.time() * 1000 @@ -294,14 +296,15 @@ class Tester(): assert(r[0] == CtapError.ERR.INVALID_SEQ) print('PASS: Test not cont') - print('Check random cont ignored') - #self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88') - #self.send_raw('\x01\x10\x00') - #try: - #cmd,r = self.recv_raw() # timeout response - #except socket.timeout: - #pass - print('PASS: random cont') + if check_timeouts: + print('Check random cont ignored') + self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88') + self.send_raw('\x01\x10\x00') + try: + cmd,r = self.recv_raw() # timeout response + except socket.timeout: + pass + print('PASS: random cont') print('Check busy') t1 = time.time() * 1000 @@ -336,11 +339,13 @@ class Tester(): self.send_raw('\x81\x00\x63') self.send_raw('\x00') + cmd,r = self.recv_raw() # busy response + self.set_cid(cid1) # finish 1st channel ping self.send_raw('\x00') self.set_cid(cid2) - cmd,r = self.recv_raw() # busy response + assert(cmd == 0xbf) assert(r[0] == CtapError.ERR.CHANNEL_BUSY) @@ -349,18 +354,19 @@ class Tester(): assert(cmd == 0x81) assert(len(r) == 0x63) - #cmd,r = self.recv_raw() # timeout - #assert(cmd == 0xbf) - #assert(r[0] == CtapError.ERR.TIMEOUT) + if check_timeouts: + cmd,r = self.recv_raw() # timeout + assert(cmd == 0xbf) + assert(r[0] == CtapError.ERR.TIMEOUT) print('PASS: busy interleaved') - - print('Test idle, wait for timeout') - sys.stdout.flush() - try: - cmd,resp = self.recv_raw() - except socket.timeout: - print('Pass: Idle') + if check_timeouts: + print('Test idle, wait for timeout') + sys.stdout.flush() + try: + cmd,resp = self.recv_raw() + except socket.timeout: + print('Pass: Idle') print('Test cid 0 is invalid') self.set_cid('\x00\x00\x00\x00') @@ -593,12 +599,9 @@ def test_find_brute_force(): if __name__ == '__main__': t = Tester() t.find_device() - #t.test_hid() - #t.test_long_ping() + # t.test_hid() + # t.test_long_ping() t.test_fido2() #test_find_brute_force() #t.test_fido2_simple() - t.test_fido2_brute_force() - - - + #t.test_fido2_brute_force() From 557a49831b9f164bfca72751181f0dde9949916a Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 22:27:00 -0400 Subject: [PATCH 06/26] dd --- targets/stm32l442/old/usbd_hid.c | 816 ------------------------------- targets/stm32l442/old/usbd_hid.h | 176 ------- 2 files changed, 992 deletions(-) delete mode 100644 targets/stm32l442/old/usbd_hid.c delete mode 100644 targets/stm32l442/old/usbd_hid.h diff --git a/targets/stm32l442/old/usbd_hid.c b/targets/stm32l442/old/usbd_hid.c deleted file mode 100644 index c8daa0d..0000000 --- a/targets/stm32l442/old/usbd_hid.c +++ /dev/null @@ -1,816 +0,0 @@ -/** - ****************************************************************************** - * @file usbd_hid.c - * @author MCD Application Team - * @brief This file provides the HID core functions. - * - * @verbatim - * - * =================================================================== - * HID Class Description - * =================================================================== - * This module manages the HID class V1.11 following the "Device Class Definition - * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". - * This driver implements the following aspects of the specification: - * - The Boot Interface Subclass - * - The Mouse protocol - * - Usage Page : Generic Desktop - * - Usage : Joystick - * - Collection : Application - * - * @note In HS mode and when the DMA is used, all variables and data structures - * dealing with the DMA during the transaction process should be 32-bit aligned. - * - * - * @endverbatim - * - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved.

- * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution 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 other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS 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. - * - ****************************************************************************** - */ - - /* BSPDependencies - - "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" - - "stm32xxxxx_{eval}{discovery}_io.c" - EndBSPDependencies */ - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_hid.h" -#include "usbd_ctlreq.h" - - -/** @addtogroup STM32_USB_DEVICE_LIBRARY - * @{ - */ - - -/** @defgroup USBD_HID - * @brief usbd core module - * @{ - */ - -/** @defgroup USBD_HID_Private_TypesDefinitions - * @{ - */ -/** - * @} - */ - - -/** @defgroup USBD_HID_Private_Defines - * @{ - */ - -/** - * @} - */ - - -/** @defgroup USBD_HID_Private_Macros - * @{ - */ -/** - * @} - */ - - - - -/** @defgroup USBD_HID_Private_FunctionPrototypes - * @{ - */ - - -static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, - uint8_t cfgidx); - -static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev, - uint8_t cfgidx); - -static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, - USBD_SetupReqTypedef *req); - -static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length); - -static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length); - -static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length); - -static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length); - -static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); - -static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum); -/** - * @} - */ - -/** @defgroup USBD_HID_Private_Variables - * @{ - */ - -USBD_ClassTypeDef USBD_HID = -{ - USBD_HID_Init, - USBD_HID_DeInit, - USBD_HID_Setup, - NULL, /*EP0_TxSent*/ - NULL, /*EP0_RxReady*/ - USBD_HID_DataIn, /*DataIn*/ - USBD_HID_DataOut, /*DataOut*/ - NULL, /*SOF */ - NULL, - NULL, - USBD_HID_GetHSCfgDesc, - USBD_HID_GetFSCfgDesc, - USBD_HID_GetOtherSpeedCfgDesc, - USBD_HID_GetDeviceQualifierDesc, -}; - -#define USBD_HID_CfgHSDesc USBD_HID_OtherSpeedCfgDesc -#define USBD_HID_CfgFSDesc USBD_HID_OtherSpeedCfgDesc - -/* USB HID device FS Configuration Descriptor */ -/*__ALIGN_BEGIN static uint8_t USBD_HID_CfgFSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =*/ -/*{*/ - /*0x09, [> bLength: Configuration Descriptor size <]*/ - /*USB_DESC_TYPE_CONFIGURATION, [> bDescriptorType: Configuration <]*/ - /*USB_HID_CONFIG_DESC_SIZ,*/ - /*[> wTotalLength: Bytes returned <]*/ - /*0x00,*/ - /*0x01, [>bNumInterfaces: 1 interface<]*/ - /*0x01, [>bConfigurationValue: Configuration value<]*/ - /*0x00, //iConfiguration: Index of string descriptor describing*/ - /*//the configuration*/ - /*0xE0, [>bmAttributes: bus powered and Support Remote Wake-up <]*/ - /*0x32, [>MaxPower 100 mA: this current is used for detecting Vbus<]*/ - - /*[>************* Descriptor of Joystick Mouse interface ***************<]*/ - /*[> 09 <]*/ - /*0x09, [>bLength: Interface Descriptor size<]*/ - /*USB_DESC_TYPE_INTERFACE,[>bDescriptorType: Interface descriptor type<]*/ - /*0x00, [>bInterfaceNumber: Number of Interface<]*/ - /*0x00, [>bAlternateSetting: Alternate setting<]*/ - /*0x01, [>bNumEndpoints<]*/ - /*0x03, [>bInterfaceClass: HID<]*/ - /*0x01, [>bInterfaceSubClass : 1=BOOT, 0=no boot<]*/ - /*0x02, [>nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse<]*/ - /*0, [>iInterface: Index of string descriptor<]*/ - /*[>******************* Descriptor of Joystick Mouse HID *******************<]*/ - /*[> 18 <]*/ - /*0x09, [>bLength: HID Descriptor size<]*/ - /*HID_DESCRIPTOR_TYPE, [>bDescriptorType: HID<]*/ - /*0x11, [>bcdHID: HID Class Spec release number<]*/ - /*0x01,*/ - /*0x00, [>bCountryCode: Hardware target country<]*/ - /*0x01, [>bNumDescriptors: Number of HID class descriptors to follow<]*/ - /*0x22, [>bDescriptorType<]*/ - /*HID_MOUSE_REPORT_DESC_SIZE,[>wItemLength: Total length of Report descriptor<]*/ - /*0x00,*/ - /*[>******************* Descriptor of Mouse endpoint *******************<]*/ - /*[> 27 <]*/ - /*0x07, [>bLength: Endpoint Descriptor size<]*/ - /*USB_DESC_TYPE_ENDPOINT, [>bDescriptorType:<]*/ - - /*HID_EPIN_ADDR, [>bEndpointAddress: Endpoint Address (IN)<]*/ - /*0x03, [>bmAttributes: Interrupt endpoint<]*/ - /*HID_EPIN_SIZE, [>wMaxPacketSize: 4 Byte max <]*/ - /*0x00,*/ - /*HID_FS_BINTERVAL, [>bInterval: Polling Interval <]*/ - /*[> 34 <]*/ -/*};*/ -/* USB HID device HS Configuration Descriptor */ -/*__ALIGN_BEGIN static uint8_t USBD_HID_CfgHSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =*/ -/*{*/ - /*0x09, [> bLength: Configuration Descriptor size <]*/ - /*USB_DESC_TYPE_CONFIGURATION, [> bDescriptorType: Configuration <]*/ - /*USB_HID_CONFIG_DESC_SIZ,*/ - /*[> wTotalLength: Bytes returned <]*/ - /*0x00,*/ - /*0x01, [>bNumInterfaces: 1 interface<]*/ - /*0x01, [>bConfigurationValue: Configuration value<]*/ - /*0x00, //iConfiguration: Index of string descriptor describing*/ - /*the configuration**/ - /*0xE0, [>bmAttributes: bus powered and Support Remote Wake-up <]*/ - /*0x32, [>MaxPower 100 mA: this current is used for detecting Vbus<]*/ - - /*[>************* Descriptor of Joystick Mouse interface ***************<]*/ - /*[> 09 <]*/ - /*0x09, [>bLength: Interface Descriptor size<]*/ - /*USB_DESC_TYPE_INTERFACE,[>bDescriptorType: Interface descriptor type<]*/ - /*0x00, [>bInterfaceNumber: Number of Interface<]*/ - /*0x00, [>bAlternateSetting: Alternate setting<]*/ - /*0x01, [>bNumEndpoints<]*/ - /*0x03, [>bInterfaceClass: HID<]*/ - /*0x01, [>bInterfaceSubClass : 1=BOOT, 0=no boot<]*/ - /*0x02, [>nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse<]*/ - /*0, [>iInterface: Index of string descriptor<]*/ - /*[>******************* Descriptor of Joystick Mouse HID *******************<]*/ - /*[> 18 <]*/ - /*0x09, [>bLength: HID Descriptor size<]*/ - /*HID_DESCRIPTOR_TYPE, [>bDescriptorType: HID<]*/ - /*0x11, [>bcdHID: HID Class Spec release number<]*/ - /*0x01,*/ - /*0x00, [>bCountryCode: Hardware target country<]*/ - /*0x01, [>bNumDescriptors: Number of HID class descriptors to follow<]*/ - /*0x22, [>bDescriptorType<]*/ - /*HID_MOUSE_REPORT_DESC_SIZE,[>wItemLength: Total length of Report descriptor<]*/ - /*0x00,*/ - /*[>******************* Descriptor of Mouse endpoint *******************<]*/ - /*[> 27 <]*/ - /*0x07, [>bLength: Endpoint Descriptor size<]*/ - /*USB_DESC_TYPE_ENDPOINT, [>bDescriptorType:<]*/ - - /*HID_EPIN_ADDR, [>bEndpointAddress: Endpoint Address (IN)<]*/ - /*0x03, [>bmAttributes: Interrupt endpoint<]*/ - /*HID_EPIN_SIZE, [>wMaxPacketSize: 4 Byte max <]*/ - /*0x00,*/ - /*HID_HS_BINTERVAL, [>bInterval: Polling Interval <]*/ - /*[> 34 <]*/ -/*};*/ - -/* USB HID device Other Speed Configuration Descriptor */ -/*__ALIGN_BEGIN static uint8_t USBD_HID_OtherSpeedCfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =*/ -/*{*/ - /*0x09, [> bLength: Configuration Descriptor size <]*/ - /*USB_DESC_TYPE_CONFIGURATION, [> bDescriptorType: Configuration <]*/ - /*USB_HID_CONFIG_DESC_SIZ,*/ - /*[> wTotalLength: Bytes returned <]*/ - /*0x00,*/ - /*0x01, [>bNumInterfaces: 1 interface<]*/ - /*0x01, [>bConfigurationValue: Configuration value<]*/ - /*0x00, //iConfiguration: Index of string descriptor describing*/ - /*//the configuration*/ - /*0xE0, [>bmAttributes: bus powered and Support Remote Wake-up <]*/ - /*0x32, [>MaxPower 100 mA: this current is used for detecting Vbus<]*/ - - /*[>************* Descriptor of Joystick Mouse interface ***************<]*/ - /*[> 09 <]*/ - /*0x09, [>bLength: Interface Descriptor size<]*/ - /*USB_DESC_TYPE_INTERFACE,[>bDescriptorType: Interface descriptor type<]*/ - /*0x00, [>bInterfaceNumber: Number of Interface<]*/ - /*0x00, [>bAlternateSetting: Alternate setting<]*/ - /*0x01, [>bNumEndpoints<]*/ - /*0x03, [>bInterfaceClass: HID<]*/ - /*0x01, [>bInterfaceSubClass : 1=BOOT, 0=no boot<]*/ - /*0x02, [>nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse<]*/ - /*0, [>iInterface: Index of string descriptor<]*/ - /*[>******************* Descriptor of Joystick Mouse HID *******************<]*/ - /*[> 18 <]*/ - /*0x09, [>bLength: HID Descriptor size<]*/ - /*HID_DESCRIPTOR_TYPE, [>bDescriptorType: HID<]*/ - /*0x11, [>bcdHID: HID Class Spec release number<]*/ - /*0x01,*/ - /*0x00, [>bCountryCode: Hardware target country<]*/ - /*0x01, [>bNumDescriptors: Number of HID class descriptors to follow<]*/ - /*0x22, [>bDescriptorType<]*/ - /*HID_MOUSE_REPORT_DESC_SIZE,[>wItemLength: Total length of Report descriptor<]*/ - /*0x00,*/ - /*[>******************* Descriptor of Mouse endpoint *******************<]*/ - /*[> 27 <]*/ - /*0x07, [>bLength: Endpoint Descriptor size<]*/ - /*USB_DESC_TYPE_ENDPOINT, [>bDescriptorType:<]*/ - - /*HID_EPIN_ADDR, [>bEndpointAddress: Endpoint Address (IN)<]*/ - /*0x03, [>bmAttributes: Interrupt endpoint<]*/ - /*HID_EPIN_SIZE, [>wMaxPacketSize: 4 Byte max <]*/ - /*0x00,*/ - /*HID_FS_BINTERVAL, [>bInterval: Polling Interval <]*/ - /*[> 34 <]*/ -/*};*/ - -__ALIGN_BEGIN static uint8_t USBD_HID_OtherSpeedCfgDesc[] __ALIGN_END = -{ - 0x09, // bLength - USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ - 0x29,// wTotalLength(LSB) - 0x00,// wTotalLength(MSB) - 1,// bNumInterfaces - 1,// bConfigurationValue - 0,// iConfiguration - 0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */ - 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ - - - //Interface 0 Descriptor - 0x09, /*bLength: Interface Descriptor size*/ - USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/ - 0,// bInterfaceNumber - 0,// bAlternateSetting - 2,// bNumEndpoints - 3,// bInterfaceClass: HID (Human Interface Device) - 0,// bInterfaceSubClass - 0,// bInterfaceProtocol - 0,// iInterface - - //HID Descriptor - 0x09, /*bLength: HID Descriptor size*/ - HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ - 0x11,// bcdHID (LSB) - 0x01,// bcdHID (MSB) - 0,// bCountryCode - 1,// bNumDescriptors - 0x22, /*bDescriptorType, HID report type*/ - ( 34 ), // wDescriptorLength(LSB) - ( 34 )>>8, // wDescriptorLength(MSB) - - //Endpoint 2 IN Descriptor - 7,// bLength - USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ - HID_EPIN_ADDR,// bEndpointAddress input - 0x03,// bAttrib interrupt type - HID_PACKET_SIZE,// wMaxPacketSize (LSB) - 0x00,// wMaxPacketSize (MSB) - HID_FS_BINTERVAL,// bInterval - - //Endpoint 3 OUT Descriptor - 7,// bLength - USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ - HID_EPOUT_ADDR,// bEndpointAddress output - 0x03,// bAttrib, interrupt type - HID_PACKET_SIZE,// wMaxPacketSize (LSB) - 0x00,// wMaxPacketSize (MSB) - HID_FS_BINTERVAL, /*bInterval: Polling Interval */ -}; - - -/* USB HID device Configuration Descriptor */ -__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END = -{ - /* 18 */ - 0x09, /*bLength: HID Descriptor size*/ - HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ - 0x11, /*bcdHID: HID Class Spec release number*/ - 0x01, - 0x00, /*bCountryCode: Hardware target country*/ - 0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/ - 0x22, /*bDescriptorType*/ - HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ - 0x00, -}; - -/* USB Standard Device Descriptor */ -__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = -{ - USB_LEN_DEV_QUALIFIER_DESC, - USB_DESC_TYPE_DEVICE_QUALIFIER, - 0x00, - 0x02, - 0x00, - 0x00, - 0x00, - 0x40, - 0x01, - 0x00, -}; - -/*__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =*/ -/*{*/ - /*0x05, 0x01,*/ - /*0x09, 0x02,*/ - /*0xA1, 0x01,*/ - /*0x09, 0x01,*/ - - /*0xA1, 0x00,*/ - /*0x05, 0x09,*/ - /*0x19, 0x01,*/ - /*0x29, 0x03,*/ - - /*0x15, 0x00,*/ - /*0x25, 0x01,*/ - /*0x95, 0x03,*/ - /*0x75, 0x01,*/ - - /*0x81, 0x02,*/ - /*0x95, 0x01,*/ - /*0x75, 0x05,*/ - /*0x81, 0x01,*/ - - /*0x05, 0x01,*/ - /*0x09, 0x30,*/ - /*0x09, 0x31,*/ - /*0x09, 0x38,*/ - - /*0x15, 0x81,*/ - /*0x25, 0x7F,*/ - /*0x75, 0x08,*/ - /*0x95, 0x03,*/ - - /*0x81, 0x06,*/ - /*0xC0, 0x09,*/ - /*0x3c, 0x05,*/ - /*0xff, 0x09,*/ - - /*0x01, 0x15,*/ - /*0x00, 0x25,*/ - /*0x01, 0x75,*/ - /*0x01, 0x95,*/ - - /*0x02, 0xb1,*/ - /*0x22, 0x75,*/ - /*0x06, 0x95,*/ - /*0x01, 0xb1,*/ - - /*0x01, 0xc0*/ -/*};*/ - -/*__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =*/ -/*{*/ - - /*0x06, 0xd0, 0xf1,// USAGE_PAGE (FIDO Alliance)*/ - /*0x09, 0x01,// USAGE (Keyboard)*/ - /*0xa1, 0x01,// COLLECTION (Application)*/ - - /*0x09, 0x20, // USAGE (Input Report Data)*/ - /*0x15, 0x00, // LOGICAL_MINIMUM (0)*/ - /*0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)*/ - /*0x75, 0x08, // REPORT_SIZE (8)*/ - /*0x95, HID_PACKET_SIZE, // REPORT_COUNT (64)*/ - /*0x81, 0x02, // INPUT (Data,Var,Abs)*/ - /*0x09, 0x21, // USAGE(Output Report Data)*/ - /*0x15, 0x00, // LOGICAL_MINIMUM (0)*/ - /*0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)*/ - /*0x75, 0x08, // REPORT_SIZE (8)*/ - /*0x95, HID_PACKET_SIZE, // REPORT_COUNT (64)*/ - /*0x91, 0x02, // OUTPUT (Data,Var,Abs)*/ - - - /*0xc0,// END_COLLECTION*/ - -/*};*/ - -#define _DEBUG() printf("%d\r\n", __LINE__) - -/** - * @} - */ - -/** @defgroup USBD_HID_Private_Functions - * @{ - */ - -/** - * @brief USBD_HID_Init - * Initialize the HID interface - * @param pdev: device instance - * @param cfgidx: Configuration index - * @retval status - */ -static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) -{ - /* Open EP IN */ - _DEBUG(); - USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE); - USBD_LL_OpenEP(pdev, HID_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_EPOUT_SIZE); - pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U; - - pdev->pClassData = USBD_malloc(sizeof (USBD_HID_HandleTypeDef)); - - if (pdev->pClassData == NULL) - { - return USBD_FAIL; - } - - ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; - - return USBD_OK; -} - -/** - * @brief USBD_HID_Init - * DeInitialize the HID layer - * @param pdev: device instance - * @param cfgidx: Configuration index - * @retval status - */ -static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev, - uint8_t cfgidx) -{ - _DEBUG(); - /* Close HID EPs */ - USBD_LL_CloseEP(pdev, HID_EPIN_ADDR); - pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 0U; - - /* FRee allocated memory */ - if(pdev->pClassData != NULL) - { - USBD_free(pdev->pClassData); - pdev->pClassData = NULL; - } - - return USBD_OK; -} - -/** - * @brief USBD_HID_Setup - * Handle the HID specific requests - * @param pdev: instance - * @param req: usb requests - * @retval status - */ -static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, - USBD_SetupReqTypedef *req) -{ - USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData; - uint16_t len = 0U; - uint8_t *pbuf = NULL; - uint16_t status_info = 0U; - USBD_StatusTypeDef ret = USBD_OK; - - _DEBUG(); - switch (req->bmRequest & USB_REQ_TYPE_MASK) - { - case USB_REQ_TYPE_CLASS : - switch (req->bRequest) - { - case HID_REQ_SET_PROTOCOL: - hhid->Protocol = (uint8_t)(req->wValue); - break; - - case HID_REQ_GET_PROTOCOL: - USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->Protocol, 1U); - break; - - case HID_REQ_SET_IDLE: - hhid->IdleState = (uint8_t)(req->wValue >> 8); - break; - - case HID_REQ_GET_IDLE: - USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->IdleState, 1U); - break; - - default: - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - printf("HID setup error %d\r\n", __LINE__); - break; - } - break; - case USB_REQ_TYPE_STANDARD: - switch (req->bRequest) - { - case USB_REQ_GET_STATUS: - if (pdev->dev_state == USBD_STATE_CONFIGURED) - { - USBD_CtlSendData (pdev, (uint8_t *)(void *)&status_info, 2U); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - } - break; - - case USB_REQ_GET_DESCRIPTOR: - if(req->wValue >> 8 == HID_REPORT_DESC) - { - len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength); - pbuf = HID_MOUSE_ReportDesc; - } - else if(req->wValue >> 8 == HID_DESCRIPTOR_TYPE) - { - pbuf = USBD_HID_Desc; - len = MIN(USB_HID_DESC_SIZ, req->wLength); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - break; - } - USBD_CtlSendData (pdev, pbuf, len); - break; - - case USB_REQ_GET_INTERFACE : - if (pdev->dev_state == USBD_STATE_CONFIGURED) - { - USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->AltSetting, 1U); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - } - break; - - case USB_REQ_SET_INTERFACE : - if (pdev->dev_state == USBD_STATE_CONFIGURED) - { - hhid->AltSetting = (uint8_t)(req->wValue); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - } - break; - - default: - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - printf("HID setup error %d\r\n", __LINE__); - break; - } - break; - - default: - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - printf("HID setup error %d\r\n", __LINE__); - break; - } - - return ret; -} - -/** - * @brief USBD_HID_SendReport - * Send HID Report - * @param pdev: device instance - * @param buff: pointer to report - * @retval status - */ -uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, - uint8_t *report, - uint16_t len) -{ - USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData; - - _DEBUG(); - if (pdev->dev_state == USBD_STATE_CONFIGURED ) - { - if(hhid->state == HID_IDLE) - { - hhid->state = HID_BUSY; - USBD_LL_Transmit (pdev, - HID_EPIN_ADDR, - report, - len); - } - } - return USBD_OK; -} - -/** - * @brief USBD_HID_GetPollingInterval - * return polling interval from endpoint descriptor - * @param pdev: device instance - * @retval polling interval - */ -uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev) -{ - uint32_t polling_interval = 0U; - - _DEBUG(); - /* HIGH-speed endpoints */ - if(pdev->dev_speed == USBD_SPEED_HIGH) - { - /* Sets the data transfer polling interval for high speed transfers. - Values between 1..16 are allowed. Values correspond to interval - of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */ - polling_interval = (((1U <<(HID_HS_BINTERVAL - 1U))) / 8U); - } - else /* LOW and FULL-speed endpoints */ - { - /* Sets the data transfer polling interval for low and full - speed transfers */ - polling_interval = HID_FS_BINTERVAL; - } - - return ((uint32_t)(polling_interval)); -} - -/** - * @brief USBD_HID_GetCfgFSDesc - * return FS configuration descriptor - * @param speed : current device speed - * @param length : pointer data length - * @retval pointer to descriptor buffer - */ -static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length) -{ - _DEBUG(); - *length = sizeof (USBD_HID_CfgFSDesc); - return USBD_HID_CfgFSDesc; -} - -/** - * @brief USBD_HID_GetCfgHSDesc - * return HS configuration descriptor - * @param speed : current device speed - * @param length : pointer data length - * @retval pointer to descriptor buffer - */ -static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length) -{ - _DEBUG(); - *length = sizeof (USBD_HID_CfgHSDesc); - return USBD_HID_CfgHSDesc; -} - -/** - * @brief USBD_HID_GetOtherSpeedCfgDesc - * return other speed configuration descriptor - * @param speed : current device speed - * @param length : pointer data length - * @retval pointer to descriptor buffer - */ -static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length) -{ - _DEBUG(); - *length = sizeof (USBD_HID_OtherSpeedCfgDesc); - return USBD_HID_OtherSpeedCfgDesc; -} - -/** - * @brief USBD_HID_DataIn - * handle data IN Stage - * @param pdev: device instance - * @param epnum: endpoint index - * @retval status - */ -static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, - uint8_t epnum) -{ - _DEBUG(); - - /* Ensure that the FIFO is empty before a new transfer, this condition could - be caused by a new transfer before the end of the previous transfer */ - ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; - return USBD_OK; -} - -static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) -{ - - _DEBUG(); - /* Ensure that the FIFO is empty before a new transfer, this condition could - be caused by a new transfer before the end of the previous transfer */ - ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; - return USBD_OK; -} - - -/** -* @brief DeviceQualifierDescriptor -* return Device Qualifier descriptor -* @param length : pointer data length -* @retval pointer to descriptor buffer -*/ -static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length) -{ - _DEBUG(); - *length = sizeof (USBD_HID_DeviceQualifierDesc); - return USBD_HID_DeviceQualifierDesc; -} - -/** - * @} - */ - - -/** - * @} - */ - - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/stm32l442/old/usbd_hid.h b/targets/stm32l442/old/usbd_hid.h deleted file mode 100644 index 3b6524e..0000000 --- a/targets/stm32l442/old/usbd_hid.h +++ /dev/null @@ -1,176 +0,0 @@ -/** - ****************************************************************************** - * @file usbd_hid.h - * @author MCD Application Team - * @brief Header file for the usbd_hid_core.c file. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved.

- * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution 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 other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS 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. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_HID_H -#define __USB_HID_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_ioreq.h" - -/** @addtogroup STM32_USB_DEVICE_LIBRARY - * @{ - */ - -/** @defgroup USBD_HID - * @brief This file is the Header file for usbd_hid.c - * @{ - */ - - -/** @defgroup USBD_HID_Exported_Defines - * @{ - */ -#define HID_PACKET_SIZE (64) - -#define HID_EPIN_ADDR 0x81U -#define HID_EPIN_SIZE HID_PACKET_SIZE - -#define HID_EPOUT_ADDR 0x01U -#define HID_EPOUT_SIZE HID_PACKET_SIZE - - -//#define USB_HID_CONFIG_DESC_SIZ 34U -#define USB_HID_DESC_SIZ 9U -#define HID_MOUSE_REPORT_DESC_SIZE 34U - -#define HID_DESCRIPTOR_TYPE 0x21U -#define HID_REPORT_DESC 0x22U - -#ifndef HID_HS_BINTERVAL - #define HID_HS_BINTERVAL 0x07U -#endif /* HID_HS_BINTERVAL */ - -#ifndef HID_FS_BINTERVAL - #define HID_FS_BINTERVAL 0x0AU -#endif /* HID_FS_BINTERVAL */ - -#define HID_REQ_SET_PROTOCOL 0x0BU -#define HID_REQ_GET_PROTOCOL 0x03U - -#define HID_REQ_SET_IDLE 0x0AU -#define HID_REQ_GET_IDLE 0x02U - -#define HID_REQ_SET_REPORT 0x09U -#define HID_REQ_GET_REPORT 0x01U -/** - * @} - */ - - -/** @defgroup USBD_CORE_Exported_TypesDefinitions - * @{ - */ -typedef enum -{ - HID_IDLE = 0, - HID_BUSY, -} -HID_StateTypeDef; - - -typedef struct -{ - uint32_t Protocol; - uint32_t IdleState; - uint32_t AltSetting; - HID_StateTypeDef state; -} -USBD_HID_HandleTypeDef; -/** - * @} - */ - - - -/** @defgroup USBD_CORE_Exported_Macros - * @{ - */ - -/** - * @} - */ - -/** @defgroup USBD_CORE_Exported_Variables - * @{ - */ - -extern USBD_ClassTypeDef USBD_HID; -#define USBD_HID_CLASS &USBD_HID -/** - * @} - */ - -/** @defgroup USB_CORE_Exported_Functions - * @{ - */ -uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, - uint8_t *report, - uint16_t len); - -uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __USB_HID_H */ -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 9c811e81d9539b28e9f8e68b01456b09dc4eac11 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 22:28:42 -0400 Subject: [PATCH 07/26] dd --- targets/stm32l442/hid_stock/usbd_hid.c | 707 ------------------------- targets/stm32l442/hid_stock/usbd_hid.h | 170 ------ 2 files changed, 877 deletions(-) delete mode 100644 targets/stm32l442/hid_stock/usbd_hid.c delete mode 100644 targets/stm32l442/hid_stock/usbd_hid.h diff --git a/targets/stm32l442/hid_stock/usbd_hid.c b/targets/stm32l442/hid_stock/usbd_hid.c deleted file mode 100644 index 5367e55..0000000 --- a/targets/stm32l442/hid_stock/usbd_hid.c +++ /dev/null @@ -1,707 +0,0 @@ -/** - ****************************************************************************** - * @file usbd_hid.c - * @author MCD Application Team - * @brief This file provides the HID core functions. - * - * @verbatim - * - * =================================================================== - * HID Class Description - * =================================================================== - * This module manages the HID class V1.11 following the "Device Class Definition - * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". - * This driver implements the following aspects of the specification: - * - The Boot Interface Subclass - * - The Mouse protocol - * - Usage Page : Generic Desktop - * - Usage : Joystick - * - Collection : Application - * - * @note In HS mode and when the DMA is used, all variables and data structures - * dealing with the DMA during the transaction process should be 32-bit aligned. - * - * - * @endverbatim - * - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved.

- * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution 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 other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS 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. - * - ****************************************************************************** - */ - - /* BSPDependencies - - "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" - - "stm32xxxxx_{eval}{discovery}_io.c" - EndBSPDependencies */ - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_hid.h" -#include "usbd_ctlreq.h" - - -/** @addtogroup STM32_USB_DEVICE_LIBRARY - * @{ - */ - - -/** @defgroup USBD_HID - * @brief usbd core module - * @{ - */ - -/** @defgroup USBD_HID_Private_TypesDefinitions - * @{ - */ -/** - * @} - */ - - -/** @defgroup USBD_HID_Private_Defines - * @{ - */ - -/** - * @} - */ - - -/** @defgroup USBD_HID_Private_Macros - * @{ - */ -/** - * @} - */ - - - - -/** @defgroup USBD_HID_Private_FunctionPrototypes - * @{ - */ - - -static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, - uint8_t cfgidx); - -static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev, - uint8_t cfgidx); - -static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, - USBD_SetupReqTypedef *req); - -static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length); - -static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length); - -static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length); - -static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length); - -static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); -/** - * @} - */ - -/** @defgroup USBD_HID_Private_Variables - * @{ - */ - -USBD_ClassTypeDef USBD_HID = -{ - USBD_HID_Init, - USBD_HID_DeInit, - USBD_HID_Setup, - NULL, /*EP0_TxSent*/ - NULL, /*EP0_RxReady*/ - USBD_HID_DataIn, /*DataIn*/ - NULL, /*DataOut*/ - NULL, /*SOF */ - NULL, - NULL, - USBD_HID_GetHSCfgDesc, - USBD_HID_GetFSCfgDesc, - USBD_HID_GetOtherSpeedCfgDesc, - USBD_HID_GetDeviceQualifierDesc, -}; - -/* USB HID device FS Configuration Descriptor */ -__ALIGN_BEGIN static uint8_t USBD_HID_CfgFSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END = -{ - 0x09, /* bLength: Configuration Descriptor size */ - USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ - USB_HID_CONFIG_DESC_SIZ, - /* wTotalLength: Bytes returned */ - 0x00, - 0x01, /*bNumInterfaces: 1 interface*/ - 0x01, /*bConfigurationValue: Configuration value*/ - 0x00, /*iConfiguration: Index of string descriptor describing - the configuration*/ - 0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */ - 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ - - /************** Descriptor of Joystick Mouse interface ****************/ - /* 09 */ - 0x09, /*bLength: Interface Descriptor size*/ - USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/ - 0x00, /*bInterfaceNumber: Number of Interface*/ - 0x00, /*bAlternateSetting: Alternate setting*/ - 0x01, /*bNumEndpoints*/ - 0x03, /*bInterfaceClass: HID*/ - 0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ - 0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ - 0, /*iInterface: Index of string descriptor*/ - /******************** Descriptor of Joystick Mouse HID ********************/ - /* 18 */ - 0x09, /*bLength: HID Descriptor size*/ - HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ - 0x11, /*bcdHID: HID Class Spec release number*/ - 0x01, - 0x00, /*bCountryCode: Hardware target country*/ - 0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/ - 0x22, /*bDescriptorType*/ - HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ - 0x00, - /******************** Descriptor of Mouse endpoint ********************/ - /* 27 */ - 0x07, /*bLength: Endpoint Descriptor size*/ - USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ - - HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/ - 0x03, /*bmAttributes: Interrupt endpoint*/ - HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */ - 0x00, - HID_FS_BINTERVAL, /*bInterval: Polling Interval */ - /* 34 */ -}; - -/* USB HID device HS Configuration Descriptor */ -__ALIGN_BEGIN static uint8_t USBD_HID_CfgHSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END = -{ - 0x09, /* bLength: Configuration Descriptor size */ - USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ - USB_HID_CONFIG_DESC_SIZ, - /* wTotalLength: Bytes returned */ - 0x00, - 0x01, /*bNumInterfaces: 1 interface*/ - 0x01, /*bConfigurationValue: Configuration value*/ - 0x00, /*iConfiguration: Index of string descriptor describing - the configuration*/ - 0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */ - 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ - - /************** Descriptor of Joystick Mouse interface ****************/ - /* 09 */ - 0x09, /*bLength: Interface Descriptor size*/ - USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/ - 0x00, /*bInterfaceNumber: Number of Interface*/ - 0x00, /*bAlternateSetting: Alternate setting*/ - 0x01, /*bNumEndpoints*/ - 0x03, /*bInterfaceClass: HID*/ - 0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ - 0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ - 0, /*iInterface: Index of string descriptor*/ - /******************** Descriptor of Joystick Mouse HID ********************/ - /* 18 */ - 0x09, /*bLength: HID Descriptor size*/ - HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ - 0x11, /*bcdHID: HID Class Spec release number*/ - 0x01, - 0x00, /*bCountryCode: Hardware target country*/ - 0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/ - 0x22, /*bDescriptorType*/ - HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ - 0x00, - /******************** Descriptor of Mouse endpoint ********************/ - /* 27 */ - 0x07, /*bLength: Endpoint Descriptor size*/ - USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ - - HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/ - 0x03, /*bmAttributes: Interrupt endpoint*/ - HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */ - 0x00, - HID_HS_BINTERVAL, /*bInterval: Polling Interval */ - /* 34 */ -}; - -/* USB HID device Other Speed Configuration Descriptor */ -__ALIGN_BEGIN static uint8_t USBD_HID_OtherSpeedCfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END = -{ - 0x09, /* bLength: Configuration Descriptor size */ - USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ - USB_HID_CONFIG_DESC_SIZ, - /* wTotalLength: Bytes returned */ - 0x00, - 0x01, /*bNumInterfaces: 1 interface*/ - 0x01, /*bConfigurationValue: Configuration value*/ - 0x00, /*iConfiguration: Index of string descriptor describing - the configuration*/ - 0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */ - 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ - - /************** Descriptor of Joystick Mouse interface ****************/ - /* 09 */ - 0x09, /*bLength: Interface Descriptor size*/ - USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/ - 0x00, /*bInterfaceNumber: Number of Interface*/ - 0x00, /*bAlternateSetting: Alternate setting*/ - 0x01, /*bNumEndpoints*/ - 0x03, /*bInterfaceClass: HID*/ - 0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ - 0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ - 0, /*iInterface: Index of string descriptor*/ - /******************** Descriptor of Joystick Mouse HID ********************/ - /* 18 */ - 0x09, /*bLength: HID Descriptor size*/ - HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ - 0x11, /*bcdHID: HID Class Spec release number*/ - 0x01, - 0x00, /*bCountryCode: Hardware target country*/ - 0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/ - 0x22, /*bDescriptorType*/ - HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ - 0x00, - /******************** Descriptor of Mouse endpoint ********************/ - /* 27 */ - 0x07, /*bLength: Endpoint Descriptor size*/ - USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ - - HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/ - 0x03, /*bmAttributes: Interrupt endpoint*/ - HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */ - 0x00, - HID_FS_BINTERVAL, /*bInterval: Polling Interval */ - /* 34 */ -}; - - -/* USB HID device Configuration Descriptor */ -__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END = -{ - /* 18 */ - 0x09, /*bLength: HID Descriptor size*/ - HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ - 0x11, /*bcdHID: HID Class Spec release number*/ - 0x01, - 0x00, /*bCountryCode: Hardware target country*/ - 0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/ - 0x22, /*bDescriptorType*/ - HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ - 0x00, -}; - -/* USB Standard Device Descriptor */ -__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = -{ - USB_LEN_DEV_QUALIFIER_DESC, - USB_DESC_TYPE_DEVICE_QUALIFIER, - 0x00, - 0x02, - 0x00, - 0x00, - 0x00, - 0x40, - 0x01, - 0x00, -}; - -__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = -{ - 0x05, 0x01, - 0x09, 0x02, - 0xA1, 0x01, - 0x09, 0x01, - - 0xA1, 0x00, - 0x05, 0x09, - 0x19, 0x01, - 0x29, 0x03, - - 0x15, 0x00, - 0x25, 0x01, - 0x95, 0x03, - 0x75, 0x01, - - 0x81, 0x02, - 0x95, 0x01, - 0x75, 0x05, - 0x81, 0x01, - - 0x05, 0x01, - 0x09, 0x30, - 0x09, 0x31, - 0x09, 0x38, - - 0x15, 0x81, - 0x25, 0x7F, - 0x75, 0x08, - 0x95, 0x03, - - 0x81, 0x06, - 0xC0, 0x09, - 0x3c, 0x05, - 0xff, 0x09, - - 0x01, 0x15, - 0x00, 0x25, - 0x01, 0x75, - 0x01, 0x95, - - 0x02, 0xb1, - 0x22, 0x75, - 0x06, 0x95, - 0x01, 0xb1, - - 0x01, 0xc0 -}; - -/** - * @} - */ - -/** @defgroup USBD_HID_Private_Functions - * @{ - */ - -/** - * @brief USBD_HID_Init - * Initialize the HID interface - * @param pdev: device instance - * @param cfgidx: Configuration index - * @retval status - */ -static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) -{ - /* Open EP IN */ - USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE); - pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U; - - pdev->pClassData = USBD_malloc(sizeof (USBD_HID_HandleTypeDef)); - - if (pdev->pClassData == NULL) - { - return USBD_FAIL; - } - - ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; - - return USBD_OK; -} - -/** - * @brief USBD_HID_Init - * DeInitialize the HID layer - * @param pdev: device instance - * @param cfgidx: Configuration index - * @retval status - */ -static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev, - uint8_t cfgidx) -{ - /* Close HID EPs */ - USBD_LL_CloseEP(pdev, HID_EPIN_ADDR); - pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 0U; - - /* FRee allocated memory */ - if(pdev->pClassData != NULL) - { - USBD_free(pdev->pClassData); - pdev->pClassData = NULL; - } - - return USBD_OK; -} - -/** - * @brief USBD_HID_Setup - * Handle the HID specific requests - * @param pdev: instance - * @param req: usb requests - * @retval status - */ -static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, - USBD_SetupReqTypedef *req) -{ - USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData; - uint16_t len = 0U; - uint8_t *pbuf = NULL; - uint16_t status_info = 0U; - USBD_StatusTypeDef ret = USBD_OK; - - switch (req->bmRequest & USB_REQ_TYPE_MASK) - { - case USB_REQ_TYPE_CLASS : - switch (req->bRequest) - { - case HID_REQ_SET_PROTOCOL: - hhid->Protocol = (uint8_t)(req->wValue); - break; - - case HID_REQ_GET_PROTOCOL: - USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->Protocol, 1U); - break; - - case HID_REQ_SET_IDLE: - hhid->IdleState = (uint8_t)(req->wValue >> 8); - break; - - case HID_REQ_GET_IDLE: - USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->IdleState, 1U); - break; - - default: - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - break; - } - break; - case USB_REQ_TYPE_STANDARD: - switch (req->bRequest) - { - case USB_REQ_GET_STATUS: - if (pdev->dev_state == USBD_STATE_CONFIGURED) - { - USBD_CtlSendData (pdev, (uint8_t *)(void *)&status_info, 2U); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - } - break; - - case USB_REQ_GET_DESCRIPTOR: - if(req->wValue >> 8 == HID_REPORT_DESC) - { - len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength); - pbuf = HID_MOUSE_ReportDesc; - } - else if(req->wValue >> 8 == HID_DESCRIPTOR_TYPE) - { - pbuf = USBD_HID_Desc; - len = MIN(USB_HID_DESC_SIZ, req->wLength); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - break; - } - USBD_CtlSendData (pdev, pbuf, len); - break; - - case USB_REQ_GET_INTERFACE : - if (pdev->dev_state == USBD_STATE_CONFIGURED) - { - USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->AltSetting, 1U); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - } - break; - - case USB_REQ_SET_INTERFACE : - if (pdev->dev_state == USBD_STATE_CONFIGURED) - { - hhid->AltSetting = (uint8_t)(req->wValue); - } - else - { - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - } - break; - - default: - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - break; - } - break; - - default: - USBD_CtlError (pdev, req); - ret = USBD_FAIL; - break; - } - - return ret; -} - -/** - * @brief USBD_HID_SendReport - * Send HID Report - * @param pdev: device instance - * @param buff: pointer to report - * @retval status - */ -uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, - uint8_t *report, - uint16_t len) -{ - USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData; - - if (pdev->dev_state == USBD_STATE_CONFIGURED ) - { - if(hhid->state == HID_IDLE) - { - hhid->state = HID_BUSY; - USBD_LL_Transmit (pdev, - HID_EPIN_ADDR, - report, - len); - } - } - return USBD_OK; -} - -/** - * @brief USBD_HID_GetPollingInterval - * return polling interval from endpoint descriptor - * @param pdev: device instance - * @retval polling interval - */ -uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev) -{ - uint32_t polling_interval = 0U; - - /* HIGH-speed endpoints */ - if(pdev->dev_speed == USBD_SPEED_HIGH) - { - /* Sets the data transfer polling interval for high speed transfers. - Values between 1..16 are allowed. Values correspond to interval - of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */ - polling_interval = (((1U <<(HID_HS_BINTERVAL - 1U))) / 8U); - } - else /* LOW and FULL-speed endpoints */ - { - /* Sets the data transfer polling interval for low and full - speed transfers */ - polling_interval = HID_FS_BINTERVAL; - } - - return ((uint32_t)(polling_interval)); -} - -/** - * @brief USBD_HID_GetCfgFSDesc - * return FS configuration descriptor - * @param speed : current device speed - * @param length : pointer data length - * @retval pointer to descriptor buffer - */ -static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length) -{ - *length = sizeof (USBD_HID_CfgFSDesc); - return USBD_HID_CfgFSDesc; -} - -/** - * @brief USBD_HID_GetCfgHSDesc - * return HS configuration descriptor - * @param speed : current device speed - * @param length : pointer data length - * @retval pointer to descriptor buffer - */ -static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length) -{ - *length = sizeof (USBD_HID_CfgHSDesc); - return USBD_HID_CfgHSDesc; -} - -/** - * @brief USBD_HID_GetOtherSpeedCfgDesc - * return other speed configuration descriptor - * @param speed : current device speed - * @param length : pointer data length - * @retval pointer to descriptor buffer - */ -static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length) -{ - *length = sizeof (USBD_HID_OtherSpeedCfgDesc); - return USBD_HID_OtherSpeedCfgDesc; -} - -/** - * @brief USBD_HID_DataIn - * handle data IN Stage - * @param pdev: device instance - * @param epnum: endpoint index - * @retval status - */ -static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, - uint8_t epnum) -{ - - /* Ensure that the FIFO is empty before a new transfer, this condition could - be caused by a new transfer before the end of the previous transfer */ - ((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE; - return USBD_OK; -} - - -/** -* @brief DeviceQualifierDescriptor -* return Device Qualifier descriptor -* @param length : pointer data length -* @retval pointer to descriptor buffer -*/ -static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length) -{ - *length = sizeof (USBD_HID_DeviceQualifierDesc); - return USBD_HID_DeviceQualifierDesc; -} - -/** - * @} - */ - - -/** - * @} - */ - - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/stm32l442/hid_stock/usbd_hid.h b/targets/stm32l442/hid_stock/usbd_hid.h deleted file mode 100644 index 2e940de..0000000 --- a/targets/stm32l442/hid_stock/usbd_hid.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - ****************************************************************************** - * @file usbd_hid.h - * @author MCD Application Team - * @brief Header file for the usbd_hid_core.c file. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved.

- * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution 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 other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS 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. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_HID_H -#define __USB_HID_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_ioreq.h" - -/** @addtogroup STM32_USB_DEVICE_LIBRARY - * @{ - */ - -/** @defgroup USBD_HID - * @brief This file is the Header file for usbd_hid.c - * @{ - */ - - -/** @defgroup USBD_HID_Exported_Defines - * @{ - */ -#define HID_EPIN_ADDR 0x81U -#define HID_EPIN_SIZE 0x04U - -#define USB_HID_CONFIG_DESC_SIZ 34U -#define USB_HID_DESC_SIZ 9U -#define HID_MOUSE_REPORT_DESC_SIZE 74U - -#define HID_DESCRIPTOR_TYPE 0x21U -#define HID_REPORT_DESC 0x22U - -#ifndef HID_HS_BINTERVAL - #define HID_HS_BINTERVAL 0x07U -#endif /* HID_HS_BINTERVAL */ - -#ifndef HID_FS_BINTERVAL - #define HID_FS_BINTERVAL 0x0AU -#endif /* HID_FS_BINTERVAL */ - -#define HID_REQ_SET_PROTOCOL 0x0BU -#define HID_REQ_GET_PROTOCOL 0x03U - -#define HID_REQ_SET_IDLE 0x0AU -#define HID_REQ_GET_IDLE 0x02U - -#define HID_REQ_SET_REPORT 0x09U -#define HID_REQ_GET_REPORT 0x01U -/** - * @} - */ - - -/** @defgroup USBD_CORE_Exported_TypesDefinitions - * @{ - */ -typedef enum -{ - HID_IDLE = 0, - HID_BUSY, -} -HID_StateTypeDef; - - -typedef struct -{ - uint32_t Protocol; - uint32_t IdleState; - uint32_t AltSetting; - HID_StateTypeDef state; -} -USBD_HID_HandleTypeDef; -/** - * @} - */ - - - -/** @defgroup USBD_CORE_Exported_Macros - * @{ - */ - -/** - * @} - */ - -/** @defgroup USBD_CORE_Exported_Variables - * @{ - */ - -extern USBD_ClassTypeDef USBD_HID; -#define USBD_HID_CLASS &USBD_HID -/** - * @} - */ - -/** @defgroup USB_CORE_Exported_Functions - * @{ - */ -uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, - uint8_t *report, - uint16_t len); - -uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __USB_HID_H */ -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From b0acd0466274f0c6f379398b12d18124a6fab8b9 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 22:29:26 -0400 Subject: [PATCH 08/26] move hid lib --- targets/stm32l442/lib/{ => usbd}/usbd_hid.c | 0 targets/stm32l442/lib/{ => usbd}/usbd_hid.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename targets/stm32l442/lib/{ => usbd}/usbd_hid.c (100%) rename targets/stm32l442/lib/{ => usbd}/usbd_hid.h (100%) diff --git a/targets/stm32l442/lib/usbd_hid.c b/targets/stm32l442/lib/usbd/usbd_hid.c similarity index 100% rename from targets/stm32l442/lib/usbd_hid.c rename to targets/stm32l442/lib/usbd/usbd_hid.c diff --git a/targets/stm32l442/lib/usbd_hid.h b/targets/stm32l442/lib/usbd/usbd_hid.h similarity index 100% rename from targets/stm32l442/lib/usbd_hid.h rename to targets/stm32l442/lib/usbd/usbd_hid.h From 285d0854724c391f19ef39a81b6c834acbef790f Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 22:29:53 -0400 Subject: [PATCH 09/26] default blocking --- targets/stm32l442/src/app.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/targets/stm32l442/src/app.h b/targets/stm32l442/src/app.h index f17c5b3..028afe2 100644 --- a/targets/stm32l442/src/app.h +++ b/targets/stm32l442/src/app.h @@ -9,7 +9,7 @@ #define DEBUG_LEVEL 1 -#define NON_BLOCK_PRINTING 1 +#define NON_BLOCK_PRINTING 0 //#define PRINTING_USE_VCOM @@ -31,4 +31,6 @@ void hw_init(void); #define LED_INIT_VALUE 0x001000 + + #endif From d383ce67bf9d5b7aaea7ced1b1b4ecc314f26eb3 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 25 Oct 2018 23:36:46 -0400 Subject: [PATCH 10/26] add button, tune color --- targets/stm32l442/src/app.h | 4 +++ targets/stm32l442/src/device.c | 59 ++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/targets/stm32l442/src/app.h b/targets/stm32l442/src/app.h index 028afe2..c75a265 100644 --- a/targets/stm32l442/src/app.h +++ b/targets/stm32l442/src/app.h @@ -31,6 +31,10 @@ void hw_init(void); #define LED_INIT_VALUE 0x001000 +// Button +#define SOLO_BUTTON_PORT GPIOA +#define SOLO_BUTTON_PIN LL_GPIO_PIN_0 +#define SKIP_BUTTON_CHECK 0 #endif diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 9b8a12c..754da57 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -2,6 +2,7 @@ #include "device.h" #include "usbd_def.h" #include "stm32l4xx.h" +#include "stm32l4xx_ll_gpio.h" #include "stm32l4xx_ll_tim.h" #include "stm32l4xx_ll_usart.h" #include "usbd_hid.h" @@ -18,6 +19,8 @@ uint32_t __65_seconds = 0; extern PCD_HandleTypeDef hpcd; +#define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) + // Timer6 overflow handler void TIM6_DAC_IRQHandler() { @@ -50,6 +53,9 @@ void delay(uint32_t ms) 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); + printf1(TAG_GEN,"hello solo\r\n"); } @@ -100,8 +106,7 @@ void heartbeat() { static int state = 0; static uint32_t val = (LED_INIT_VALUE >> 8) & 0xff; - // int but = IS_BUTTON_PRESSED(); - int but = 0; + int but = IS_BUTTON_PRESSED(); if (state) { @@ -116,13 +121,9 @@ void heartbeat() { state = !state; } - // int c = PCD_GET_EP_TX_CNT(USB,1); - // int c = PCD_GET_EP_TX_STATUS(USB,1); - // printf("tx counter: %x\r\n",PCD_GET_EP_TX_CNT(USB,1)); - - // if (but) RGB(val * 2); - // else - led_rgb((val << 16) | (val*2 << 8)); + if (but) led_rgb(val * 2); + else + led_rgb((val << 16) | (val*2 << 8)); } void authenticator_read_state(AuthenticatorState * a) @@ -171,7 +172,47 @@ void device_manage() int ctap_user_presence_test() { +#if SKIP_BUTTON_CHECK return 1; +#endif + + uint32_t t1 = millis(); + led_rgb(0xff3520); + +#if USE_BUTTON_DELAY + delay(3000); + led_rgb(0x001040); + delay(50); + return 1; +#endif +while (IS_BUTTON_PRESSED()) +{ + if (t1 + 5000 < millis()) + { + printf1(TAG_GEN,"Button not pressed\n"); + return 0; + } +} + +t1 = millis(); + +do +{ + if (t1 + 5000 < millis()) + { + return 0; + } + if (! IS_BUTTON_PRESSED()) + continue; + delay(1); +} +while (! IS_BUTTON_PRESSED()); + +led_rgb(0x001040); + +delay(50); + +return 1; } int ctap_generate_rng(uint8_t * dst, size_t num) From 528e62173d4495c78911a92a9d3360fe57a2526d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 26 Oct 2018 00:04:10 -0400 Subject: [PATCH 11/26] nonvolatile data --- targets/stm32l442/src/app.h | 2 +- targets/stm32l442/src/device.c | 44 +++++++++++++++++++++++++++++--- targets/stm32l442/stm32l432xx.ld | 26 +++++++++---------- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/targets/stm32l442/src/app.h b/targets/stm32l442/src/app.h index c75a265..0db87d3 100644 --- a/targets/stm32l442/src/app.h +++ b/targets/stm32l442/src/app.h @@ -35,6 +35,6 @@ void hw_init(void); #define SOLO_BUTTON_PORT GPIOA #define SOLO_BUTTON_PIN LL_GPIO_PIN_0 -#define SKIP_BUTTON_CHECK 0 +#define SKIP_BUTTON_CHECK 1 #endif diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 754da57..08a2d1b 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -16,6 +16,23 @@ #include "fifo.h" #include "log.h" + +#define PAGE_SIZE 2048 +#define PAGES 128 +// Pages 120-127 are data +#define COUNTER_PAGE (PAGES - 3) +#define STATE2_PAGE (PAGES - 2) +#define STATE1_PAGE (PAGES - 1) + + +#define APPLICATION_START_PAGE (0) +#define APPLICATION_START_ADDR flash_addr(APPLICATION_START_PAGE) + +#define APPLICATION_END_PAGE ((PAGES - 8)) // 120 is NOT included in application +#define APPLICATION_END_ADDR (flash_addr(APPLICATION_END_PAGE)-4) // NOT included in application + +#define AUTH_WORD_ADDR (flash_addr(APPLICATION_END_PAGE)-4) + uint32_t __65_seconds = 0; extern PCD_HandleTypeDef hpcd; @@ -128,24 +145,43 @@ void heartbeat() void authenticator_read_state(AuthenticatorState * a) { - + uint32_t * ptr = (uint32_t *)flash_addr(STATE1_PAGE); + memmove(a,ptr,sizeof(AuthenticatorState)); } void authenticator_read_backup_state(AuthenticatorState * a) { - + uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE); + memmove(a,ptr,sizeof(AuthenticatorState)); } // Return 1 yes backup is init'd, else 0 -//void authenticator_initialize() int authenticator_is_backup_initialized() { - return 0; + uint8_t header[16]; + uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE); + memmove(header,ptr,16); + AuthenticatorState * state = (AuthenticatorState*)header; + return state->is_initialized == INITIALIZED_MARKER; } void authenticator_write_state(AuthenticatorState * a, int backup) { + uint32_t * ptr; + if (! backup) + { + ptr = (uint32_t *)(PAGE_SIZE*STATE1_PAGE); + flash_erase_page(STATE1_PAGE); + flash_write(flash_addr(STATE1_PAGE), (uint8_t*)a, sizeof(AuthenticatorState)); + } + else + { + ptr = (uint32_t *)(PAGE_SIZE*STATE2_PAGE); + flash_erase_page(STATE2_PAGE); + + flash_write(flash_addr(STATE2_PAGE), (uint8_t*)a, sizeof(AuthenticatorState)); + } } void device_manage() diff --git a/targets/stm32l442/stm32l432xx.ld b/targets/stm32l442/stm32l432xx.ld index 70f0efe..762abfe 100644 --- a/targets/stm32l442/stm32l432xx.ld +++ b/targets/stm32l442/stm32l432xx.ld @@ -41,7 +41,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ /* Specify the memory areas */ MEMORY { -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 240K /* Leave out 16 Kb for data */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K SRAM2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K } @@ -83,8 +83,8 @@ SECTIONS . = ALIGN(8); } >FLASH - .ARM.extab : - { + .ARM.extab : + { . = ALIGN(8); *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(8); @@ -105,7 +105,7 @@ SECTIONS PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(8); } >FLASH - + .init_array : { . = ALIGN(8); @@ -129,7 +129,7 @@ SECTIONS _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : + .data : { . = ALIGN(8); _sdata = .; /* create a global symbol at data start */ @@ -142,11 +142,11 @@ SECTIONS _sisram2 = LOADADDR(.sram2); - /* CCM-RAM section - * - * IMPORTANT NOTE! + /* CCM-RAM section + * + * IMPORTANT NOTE! * If initialized variables will be placed in this section, - * the startup code needs to be modified to copy the init-values. + * the startup code needs to be modified to copy the init-values. */ .sram2 : { @@ -154,12 +154,12 @@ SECTIONS _ssram2 = .; /* create a global symbol at sram2 start */ *(.sram2) *(.sram2*) - + . = ALIGN(8); _esram2 = .; /* create a global symbol at sram2 end */ } >SRAM2 AT> FLASH - + /* Uninitialized data section */ . = ALIGN(4); .bss : @@ -187,7 +187,7 @@ SECTIONS . = ALIGN(8); } >RAM - + /* Remove information from the standard libraries */ /DISCARD/ : @@ -199,5 +199,3 @@ SECTIONS .ARM.attributes 0 : { *(.ARM.attributes) } } - - From 27a2e130391ee36ff8507479e6428eca8b4331e5 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 26 Oct 2018 00:15:41 -0400 Subject: [PATCH 12/26] atomic count --- targets/stm32l442/src/device.c | 46 ++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 08a2d1b..0dd07e6 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -170,20 +170,57 @@ void authenticator_write_state(AuthenticatorState * a, int backup) uint32_t * ptr; if (! backup) { - ptr = (uint32_t *)(PAGE_SIZE*STATE1_PAGE); flash_erase_page(STATE1_PAGE); flash_write(flash_addr(STATE1_PAGE), (uint8_t*)a, sizeof(AuthenticatorState)); } else { - ptr = (uint32_t *)(PAGE_SIZE*STATE2_PAGE); flash_erase_page(STATE2_PAGE); flash_write(flash_addr(STATE2_PAGE), (uint8_t*)a, sizeof(AuthenticatorState)); } } +uint32_t ctap_atomic_count(int sel) +{ + int offset = 0; + uint32_t count; + uint32_t zero = 0; + uint32_t * ptr = (uint32_t *)flash_addr(COUNTER_PAGE); + + if (sel != 0) + { + printf2(TAG_ERR,"counter2 not imple\n"); + exit(1); + } + + for (offset = 0; offset < PAGE_SIZE/4; offset += 1) // wear-level the flash + { + count = *(ptr+offset); + if (count != 0) + { + count++; + offset++; + if (offset == PAGE_SIZE/4) + { + offset = 0; + flash_erase_page(COUNTER_PAGE); + } + else + { + flash_write(flash_addr(COUNTER_PAGE)+offset-1,(uint8_t*)&zero,4); + } + flash_write(flash_addr(COUNTER_PAGE)+offset,(uint8_t*)&count,4); + + break; + } + } + + return count; +} + + void device_manage() { #if NON_BLOCK_PRINTING @@ -257,11 +294,6 @@ int ctap_generate_rng(uint8_t * dst, size_t num) return 1; } -uint32_t ctap_atomic_count(int sel) -{ - static uint32_t c = 4; - return c++; -} int ctap_user_verification(uint8_t arg) { From b9e51f6125a730cb1408cc96beff4582261dda90 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 26 Oct 2018 00:52:32 -0400 Subject: [PATCH 13/26] initial on-device key generation --- fido2/crypto.h | 2 +- fido2/ctap.c | 7 +++++-- targets/stm32l442/src/crypto.c | 27 +++++++++++++++++---------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/fido2/crypto.h b/fido2/crypto.h index a0b17f2..497ebf5 100644 --- a/fido2/crypto.h +++ b/fido2/crypto.h @@ -49,7 +49,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); -// Key must be 32 bytes #define CRYPTO_TRANSPORT_KEY NULL #define CRYPTO_MASTER_KEY NULL @@ -61,6 +60,7 @@ void crypto_aes256_decrypt(uint8_t * buf, int lenth); void crypto_aes256_encrypt(uint8_t * buf, int lenth); void crypto_reset_master_secret(); +void crypto_load_master_secret(uint8_t * key); extern const uint8_t attestation_cert_der[]; diff --git a/fido2/ctap.c b/fido2/ctap.c index 2e62a01..2d3bb48 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -1253,6 +1253,9 @@ static void ctap_state_init() { // Set to 0xff instead of 0x00 to be easier on flash memset(&STATE, 0xff, sizeof(AuthenticatorState)); + // Fresh RNG for key + ctap_generate_rng(STATE.key_space, KEY_SPACE_BYTES); + STATE.is_initialized = INITIALIZED_MARKER; STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS; STATE.is_pin_set = 0; @@ -1286,6 +1289,8 @@ void ctap_init() } } + crypto_load_master_secret(STATE.key_space); + if (ctap_is_pin_set()) { printf1(TAG_STOR,"pin code: \"%s\"\n", STATE.pin_code); @@ -1303,7 +1308,6 @@ void ctap_init() printf1(TAG_ERR, "DEVICE LOCKED!\n"); } - if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1) { printf2(TAG_ERR,"Error, rng failed\n"); @@ -1513,4 +1517,3 @@ void ctap_reset() crypto_reset_master_secret(); // Not sure what the significance of this is?? } - diff --git a/targets/stm32l442/src/crypto.c b/targets/stm32l442/src/crypto.c index 1a4af35..6d7a351 100644 --- a/targets/stm32l442/src/crypto.c +++ b/targets/stm32l442/src/crypto.c @@ -53,12 +53,8 @@ static const uint8_t * _signing_key = NULL; static int _key_len = 0; // Secrets for testing only -static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff" - "\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00"; - -static uint8_t transport_secret[32] = "\x10\x01\x22\x33\x44\x55\x66\x77\x87\x90\x0a\xbb\x3c\xd8\xee\xff" - "\xff\xee\x8d\x1c\x3b\xfa\x99\x88\x77\x86\x55\x44\xd3\xff\x33\x00"; - +static uint8_t master_secret[64]; +static uint8_t transport_secret[32]; void crypto_sha256_init() @@ -66,9 +62,20 @@ void crypto_sha256_init() sha256_init(&sha256_ctx); } + +void crypto_load_master_secret(uint8_t * key) +{ +#if KEY_SPACE_BYTES < 96 +#error "need more key bytes" +#endif + memmove(master_secret, key, 64); + memmove(transport_secret, key+64, 32); +} + void crypto_reset_master_secret() { - ctap_generate_rng(master_secret, 32); + memset(master_secret, 0, 64); + ctap_generate_rng(master_secret, 64); } @@ -96,7 +103,7 @@ void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac) if (key == CRYPTO_MASTER_KEY) { key = master_secret; - klen = sizeof(master_secret); + klen = sizeof(master_secret)/2; } if(klen > 64) @@ -125,7 +132,7 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac) if (key == CRYPTO_MASTER_KEY) { key = master_secret; - klen = sizeof(master_secret); + klen = sizeof(master_secret)/2; } @@ -224,7 +231,7 @@ void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, ui crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey); crypto_sha256_update(data, len); crypto_sha256_update(data2, len2); - crypto_sha256_update(master_secret, 32); + crypto_sha256_update(master_secret, 32); // TODO AES crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey); } From bee17a3fbe89949cd6bd29d346762a7c7cabdc55 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 26 Oct 2018 00:54:32 -0400 Subject: [PATCH 14/26] update pc version --- fido2/crypto.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fido2/crypto.c b/fido2/crypto.c index 3a52097..35cf333 100644 --- a/fido2/crypto.c +++ b/fido2/crypto.c @@ -53,11 +53,9 @@ static const uint8_t * _signing_key = NULL; static int _key_len = 0; // Secrets for testing only -static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff" - "\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00"; +static uint8_t master_secret[32]; -static uint8_t transport_secret[32] = "\x10\x01\x22\x33\x44\x55\x66\x77\x87\x90\x0a\xbb\x3c\xd8\xee\xff" - "\xff\xee\x8d\x1c\x3b\xfa\x99\x88\x77\x86\x55\x44\xd3\xff\x33\x00"; +static uint8_t transport_secret[32]; @@ -71,6 +69,11 @@ void crypto_reset_master_secret() ctap_generate_rng(master_secret, 32); } +void crypto_load_master_secret(uint8_t * key) +{ + memmove(master_secret, key, 32); + memmove(transport_secret, key+32, 32); +} void crypto_sha256_update(uint8_t * data, size_t len) { @@ -353,5 +356,3 @@ const uint16_t attestation_key_size = sizeof(attestation_key)-1; #else #error "No crypto implementation defined" #endif - - From 2f911368dab081ff6f4252d0857772162d8ffdd8 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 27 Oct 2018 18:55:32 -0400 Subject: [PATCH 15/26] make count atomic --- targets/stm32l442/src/device.c | 85 +++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 0dd07e6..ed56c79 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -19,8 +19,9 @@ #define PAGE_SIZE 2048 #define PAGES 128 -// Pages 120-127 are data -#define COUNTER_PAGE (PAGES - 3) +// Pages 119-127 are data +#define COUNTER2_PAGE (PAGES - 4) +#define COUNTER1_PAGE (PAGES - 3) #define STATE2_PAGE (PAGES - 2) #define STATE1_PAGE (PAGES - 1) @@ -28,7 +29,7 @@ #define APPLICATION_START_PAGE (0) #define APPLICATION_START_ADDR flash_addr(APPLICATION_START_PAGE) -#define APPLICATION_END_PAGE ((PAGES - 8)) // 120 is NOT included in application +#define APPLICATION_END_PAGE ((PAGES - 9)) // 119 is NOT included in application #define APPLICATION_END_ADDR (flash_addr(APPLICATION_END_PAGE)-4) // NOT included in application #define AUTH_WORD_ADDR (flash_addr(APPLICATION_END_PAGE)-4) @@ -74,6 +75,7 @@ void device_init() LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); printf1(TAG_GEN,"hello solo\r\n"); + } void usbhid_init() @@ -167,7 +169,6 @@ int authenticator_is_backup_initialized() void authenticator_write_state(AuthenticatorState * a, int backup) { - uint32_t * ptr; if (! backup) { flash_erase_page(STATE1_PAGE); @@ -185,9 +186,15 @@ void authenticator_write_state(AuthenticatorState * a, int backup) uint32_t ctap_atomic_count(int sel) { int offset = 0; - uint32_t count; - uint32_t zero = 0; - uint32_t * ptr = (uint32_t *)flash_addr(COUNTER_PAGE); + uint32_t * ptr = (uint32_t *)flash_addr(COUNTER1_PAGE); + uint32_t erases = *(uint32_t *)flash_addr(COUNTER2_PAGE); + if (erases == 0xffffffff) + { + erases = 1; + flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); + } + + uint32_t lastc = 0; if (sel != 0) { @@ -195,29 +202,63 @@ uint32_t ctap_atomic_count(int sel) exit(1); } - for (offset = 0; offset < PAGE_SIZE/4; offset += 1) // wear-level the flash + for (offset = 0; offset < PAGE_SIZE/4; offset += 2) // wear-level the flash { - count = *(ptr+offset); - if (count != 0) + if (ptr[offset] != 0xffffffff) { - count++; - offset++; - if (offset == PAGE_SIZE/4) + if (ptr[offset] < lastc) { - offset = 0; - flash_erase_page(COUNTER_PAGE); + printf2(TAG_ERR,"Error, count went down!\r\n"); } - else - { - flash_write(flash_addr(COUNTER_PAGE)+offset-1,(uint8_t*)&zero,4); - } - flash_write(flash_addr(COUNTER_PAGE)+offset,(uint8_t*)&count,4); - + lastc = ptr[offset]; + } + else + { break; } } - return count; + if (!lastc) // Happens on initialization as well. + { + printf("warning, power interrupted during previous count. Restoring.\r\n"); + // there are 32 counts per page + lastc = erases * 32; + flash_erase_page(COUNTER1_PAGE); + flash_write(flash_addr(COUNTER1_PAGE), (uint8_t*)&lastc, 4); + + erases++; + flash_erase_page(COUNTER2_PAGE); + flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); + } + + lastc++; + + if (lastc/32 > erases) + { + printf("warning, power interrupted, erases mark, restoring\r\n"); + erases = lastc/32 + 1; + flash_erase_page(COUNTER2_PAGE); + flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); + } + + if (offset == PAGE_SIZE/4) + { + if (lastc/32 > erases) + { + printf("warning, power interrupted, erases mark, restoring\r\n"); + } + erases = lastc/32 + 1; + flash_erase_page(COUNTER2_PAGE); + flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); + + flash_erase_page(COUNTER1_PAGE); + } + else + { + flash_write(flash_addr(COUNTER1_PAGE) + offset * 4, (uint8_t*)&lastc, 4); + } + + return lastc; } From ac89f0c227519d081f13aabc8657b60fe442f0b5 Mon Sep 17 00:00:00 2001 From: nickray Date: Sun, 28 Oct 2018 14:30:06 +0100 Subject: [PATCH 16/26] Update udev.md --- docs/udev.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/udev.md b/docs/udev.md index e6ff08c..0ff860d 100644 --- a/docs/udev.md +++ b/docs/udev.md @@ -39,7 +39,11 @@ Try reading and writing to the device node you identified in the previous step. * write: try `echo "hello, Solo" > /dev/hidraw0`. Again, if you don't get denied permission, you're OK. ## Which rule should I use, and how do I do it? -Simplest is probably to copy [Yubico's rule file](https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules) to `/etc/udev/rules.d/fido.rules` on your system. This contains rules for Yubico's keys, the U2F Zero, and many others. The relevant line for U2F Zero is: +Simplest is probably to copy [Yubico's rule file](https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules) to `/etc/udev/rules.d/fido.rules` on your system, for instance: +``` +$ (cd /etc/udev/rules.d/ && sudo curl https://raw.githubusercontent.com/Yubico/libu2f-host/master/70-u2f.rules -O) +``` +This contains rules for Yubico's keys, the U2F Zero, and many others. The relevant line for U2F Zero is: ``` KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess" ``` From 2fd96f8e4b3b34c24e3af48f9babc5373eacd0e6 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 28 Oct 2018 16:30:55 -0400 Subject: [PATCH 17/26] pass fido2 tests --- fido2/ctap.c | 201 +++++++++++++----- fido2/ctap.h | 16 +- fido2/ctap_parse.c | 135 +++++++++--- fido2/ctap_parse.h | 2 +- fido2/ctaphid.c | 334 +++++++++++++++++------------- fido2/ctaphid.h | 10 +- fido2/device.h | 6 +- fido2/main.c | 27 ++- fido2/storage.h | 5 +- targets/stm32l442/Makefile | 4 +- targets/stm32l442/src/device.c | 108 ++++++++-- targets/stm32l442/src/fifo.c | 28 ++- targets/stm32l442/src/fifo.h | 24 ++- targets/stm32l442/src/flash.c | 4 +- targets/stm32l442/src/init.c | 33 ++- targets/stm32l442/src/main.c | 166 ++++++++++++++- targets/stm32l442/stm32l432xx.ld | 2 +- tools/ctap_test.py | 41 +++- tools/gencert/cbytes.py | 5 +- tools/gencert/gen_intermediate.sh | 22 ++ tools/gencert/genca.sh | 7 +- tools/gencert/print_x_y.py | 16 ++ tools/gencert/verify_certs.sh | 22 ++ 23 files changed, 900 insertions(+), 318 deletions(-) create mode 100644 tools/gencert/gen_intermediate.sh create mode 100644 tools/gencert/print_x_y.py create mode 100644 tools/gencert/verify_certs.sh diff --git a/fido2/ctap.c b/fido2/ctap.c index 2d3bb48..c3b4a4c 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -26,6 +26,7 @@ #include "cbor.h" #include "ctap.h" +#include "ctaphid.h" #include "ctap_parse.h" #include "ctap_errors.h" #include "cose_key.h" @@ -43,6 +44,7 @@ uint8_t PIN_TOKEN[PIN_TOKEN_SIZE]; uint8_t KEY_AGREEMENT_PUB[64]; static uint8_t KEY_AGREEMENT_PRIV[32]; static uint8_t PIN_CODE_HASH[32]; +static int8_t PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS; AuthenticatorState STATE; @@ -264,11 +266,11 @@ static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input, return 0; } -void make_auth_tag(struct rpId * rp, CTAP_userEntity * user, uint32_t count, uint8_t * tag) +void make_auth_tag(uint8_t * nonce, CTAP_userEntity * user, uint32_t count, uint8_t * tag) { uint8_t hashbuf[32]; crypto_sha256_hmac_init(NULL, 0, hashbuf); - crypto_sha256_update(rp->id, rp->size); + crypto_sha256_update(nonce, CREDENTIAL_NONCE_SIZE); crypto_sha256_update(user->id, user->id_size); crypto_sha256_update(user->name, strnlen((const char*)user->name, USER_NAME_LIMIT)); crypto_sha256_update((uint8_t*)&count, 4); @@ -283,21 +285,19 @@ static uint32_t auth_data_update_count(CTAP_authDataHeader * authData) if (count == 0) // count 0 will indicate invalid token { count = ctap_atomic_count( 0 ); + } uint8_t * byte = (uint8_t*) &authData->signCount; - *byte++ = count & 0xff; - count = count >> 8; - *byte++ = count & 0xff; - count = count >> 8; - *byte++ = count & 0xff; - count = count >> 8; - *byte++ = count & 0xff; + *byte++ = (count >> 0) & 0xff; + *byte++ = (count >> 8) & 0xff; + *byte++ = (count >> 16) & 0xff; + *byte++ = (count >> 24) & 0xff; return count; } -static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype) +static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz) { CborEncoder cose_key; int auth_data_sz, ret; @@ -318,10 +318,24 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au count = auth_data_update_count(&authData->head); - authData->head.flags = (ctap_user_presence_test() << 0); + device_set_status(CTAPHID_STATUS_UPNEEDED); + int but = ctap_user_presence_test(); + + if (!but) + { + return CTAP2_ERR_OPERATION_DENIED; + } + else if (but < 0) // Cancel + { + return CTAP2_ERR_KEEPALIVE_CANCEL; + } + device_set_status(CTAPHID_STATUS_PROCESSING); + + authData->head.flags = (but << 0); authData->head.flags |= (ctap_user_verification(0) << 2); + if (credtype != 0) { // add attestedCredentialData @@ -338,19 +352,19 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au #else memset((uint8_t*)&authData->attest.credential, 0, sizeof(struct Credential)); - // Make a tag we can later check to make sure this is a token we made - make_auth_tag(rp, user, count, authData->attest.credential.tag); + ctap_generate_rng(authData->attest.credential.nonce, CREDENTIAL_NONCE_SIZE); memmove(&authData->attest.credential.enc.user, user, sizeof(CTAP_userEntity)); //TODO encrypt this authData->attest.credential.enc.count = count; + // Make a tag we can later check to make sure this is a token we made + make_auth_tag(authData->attest.credential.nonce, user, count, authData->attest.credential.tag); + crypto_aes256_init(CRYPTO_TRANSPORT_KEY, NULL); crypto_aes256_encrypt((uint8_t*)&authData->attest.credential.enc, CREDENTIAL_ENC_SIZE); ctap_generate_cose_key(&cose_key, (uint8_t*)&authData->attest.credential, sizeof(struct Credential), credtype, algtype); - printf1(TAG_MC,"COSE_KEY: "); dump_hex1(TAG_MC, cose_key_buf, cbor_encoder_get_buffer_size(&cose_key, cose_key_buf)); - auth_data_sz = sizeof(CTAP_authData) + cbor_encoder_get_buffer_size(&cose_key, cose_key_buf); #endif @@ -367,7 +381,8 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au check_ret(ret); } - return auth_data_sz; + if (sz) *sz = auth_data_sz; + return 0; } @@ -419,7 +434,6 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa crypto_sha256_update(clientDataHash, CLIENT_DATA_HASH_SIZE); crypto_sha256_final(hashbuf); - printf1(TAG_GREEN, "sha256: "); dump_hex1(TAG_DUMP,hashbuf,32); crypto_ecc256_sign(hashbuf, 32, sigbuf); return ctap_encode_der_sig(sigbuf,sigder); @@ -471,13 +485,8 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len) int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * desc) { uint8_t tag[16]; - if (desc->type != PUB_KEY_CRED_PUB_KEY) - { - printf1(TAG_GA,"unsupported credential type: %d\n", desc->type); - return 0; - } - make_auth_tag(rp, &desc->credential.enc.user, desc->credential.enc.count, tag); + make_auth_tag(desc->credential.nonce, &desc->credential.enc.user, desc->credential.enc.count, tag); return (memcmp(desc->credential.tag, tag, CREDENTIAL_TAG_SIZE) == 0); } @@ -519,6 +528,12 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt } } + if (MC.up) + { + return CTAP2_ERR_INVALID_OPTION; + } + + crypto_aes256_init(CRYPTO_TRANSPORT_KEY, NULL); for (i = 0; i < MC.excludeListSize; i++) { ret = parse_credential_descriptor(&MC.excludeList, excl_cred); @@ -528,8 +543,11 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt } check_retr(ret); + crypto_aes256_reset_iv(NULL); + crypto_aes256_decrypt((uint8_t*)& excl_cred->credential.enc, CREDENTIAL_ENC_SIZE); if (ctap_authenticate_credential(&MC.rp, excl_cred)) { + printf1(TAG_MC, "Cred %d failed!\r\n",i); return CTAP2_ERR_CREDENTIAL_EXCLUDED; } @@ -540,9 +558,11 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt CborEncoder map; ret = cbor_encoder_create_map(encoder, &map, 3); check_ret(ret); + int32_t auth_data_sz; - int auth_data_sz = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf), - &MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier); + ret = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf), + &MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz); + check_retr(ret); crypto_ecc256_load_attestation_key(); int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder); @@ -724,11 +744,6 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr crypto_ecc256_load_key((uint8_t*)&cred->credential, sizeof(struct Credential), NULL, 0); - /*printf1(TAG_GREEN,"auth_data_buf: "); dump_hex1(TAG_DUMP, auth_data_buf, sizeof(CTAP_authDataHeader));*/ - /*printf1(TAG_GREEN,"clientdatahash: "); dump_hex1(TAG_DUMP, clientDataHash, 32);*/ - /*printf1(TAG_GREEN,"credential: # %d\n", cred->credential.enc.count);*/ - /*dump_hex1(TAG_DUMP, clientDataHash, 32);*/ - int sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder); { @@ -801,12 +816,16 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) } } - + if (!GA.rp.size || !GA.clientDataHashPresent) + { + return CTAP2_ERR_MISSING_PARAMETER; + } CborEncoder map; ret = cbor_encoder_create_map(encoder, &map, 5); check_ret(ret); - ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0); + ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL); + check_retr(ret); printf1(TAG_GA, "ALLOW_LIST has %d creds\n", GA.credLen); /*for (int j = 0; j < GA.credLen; j++)*/ @@ -834,13 +853,13 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) else { printf2(TAG_ERR,"Error, no authentic credential\n"); - return CTAP2_ERR_CREDENTIAL_NOT_VALID; + return CTAP2_ERR_NO_CREDENTIALS; } - printf1(TAG_RED,"resulting order of creds:\n"); + printf1(TAG_GA,"resulting order of creds:\n"); for (int j = 0; j < GA.credLen; j++) { - printf1(TAG_RED,"CRED ID (# %d)\n", GA.creds[j].credential.enc.count); + printf1(TAG_GA,"CRED ID (# %d)\n", GA.creds[j].credential.enc.count); } { @@ -861,6 +880,18 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) return 0; } +// Return how many trailing zeros in a buffer +static int trailing_zeros(uint8_t * buf, int indx) +{ + int c = 0; + while(0==buf[indx] && indx) + { + indx--; + c++; + } + return c; +} + uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platform_pubkey, uint8_t * pinAuth, uint8_t * pinHashEnc) { uint8_t shared_secret[32]; @@ -876,7 +907,11 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor { if (ctap_device_locked()) { - return CTAP2_ERR_OPERATION_DENIED; + return CTAP2_ERR_PIN_BLOCKED; + } + if (ctap_device_boot_locked()) + { + return CTAP2_ERR_PIN_AUTH_BLOCKED; } } @@ -911,25 +946,31 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor crypto_aes256_decrypt(pinEnc, len); - printf1(TAG_CP,"new pin: %s\n", pinEnc); - ret = strnlen((const char *)pinEnc, NEW_PIN_ENC_MAX_SIZE); - if (ret == NEW_PIN_ENC_MAX_SIZE) + + ret = trailing_zeros(pinEnc, NEW_PIN_ENC_MIN_SIZE - 1); + ret = NEW_PIN_ENC_MIN_SIZE - ret; + + if (ret < NEW_PIN_MIN_SIZE || ret >= NEW_PIN_MAX_SIZE) { - printf2(TAG_ERR,"No NULL terminator in new pin string\n"); - return CTAP1_ERR_OTHER; - } - else if (ret < 4) - { - printf2(TAG_ERR,"new PIN is too short\n"); + printf2(TAG_ERR,"new PIN is too short or too long [%d bytes]\n", ret); return CTAP2_ERR_PIN_POLICY_VIOLATION; } + else + { + printf1(TAG_CP,"new pin: %s [%d bytes]\n", pinEnc, ret); + dump_hex1(TAG_CP, pinEnc, ret); + } if (ctap_is_pin_set()) { if (ctap_device_locked()) { - return CTAP2_ERR_OPERATION_DENIED; + return CTAP2_ERR_PIN_BLOCKED; + } + if (ctap_device_boot_locked()) + { + return CTAP2_ERR_PIN_AUTH_BLOCKED; } crypto_aes256_reset_iv(NULL); crypto_aes256_decrypt(pinHashEnc, 16); @@ -937,6 +978,10 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor { crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); ctap_decrement_pin_attempts(); + if (ctap_device_boot_locked()) + { + return CTAP2_ERR_PIN_AUTH_BLOCKED; + } return CTAP2_ERR_PIN_INVALID; } else @@ -976,6 +1021,10 @@ uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubke // Generate new keyAgreement pair crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); ctap_decrement_pin_attempts(); + if (ctap_device_boot_locked()) + { + return CTAP2_ERR_PIN_AUTH_BLOCKED; + } return CTAP2_ERR_PIN_INVALID; } @@ -995,6 +1044,20 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length) uint8_t pinTokenEnc[PIN_TOKEN_SIZE]; int ret = ctap_parse_client_pin(&CP,request,length); + switch(CP.subCommand) + { + case CP_cmdSetPin: + case CP_cmdChangePin: + case CP_cmdGetPinToken: + if (ctap_device_locked()) + { + return CTAP2_ERR_PIN_BLOCKED; + } + if (ctap_device_boot_locked()) + { + return CTAP2_ERR_PIN_AUTH_BLOCKED; + } + } if (ret != 0) { @@ -1104,7 +1167,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length) check_ret(ret); } - if (num_map) + if (num_map || CP.getRetries) { ret = cbor_encoder_close_container(encoder, &map); check_ret(ret); @@ -1141,10 +1204,14 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) { case CTAP_MAKE_CREDENTIAL: case CTAP_GET_ASSERTION: - case CTAP_CLIENT_PIN: if (ctap_device_locked()) { - status = CTAP2_ERR_OPERATION_DENIED; + status = CTAP2_ERR_PIN_BLOCKED; + goto done; + } + if (ctap_device_boot_locked()) + { + status = CTAP2_ERR_PIN_AUTH_BLOCKED; goto done; } break; @@ -1153,6 +1220,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) switch(cmd) { case CTAP_MAKE_CREDENTIAL: + device_set_status(CTAPHID_STATUS_PROCESSING); printf1(TAG_CTAP,"CTAP_MAKE_CREDENTIAL\n"); t1 = millis(); status = ctap_make_credential(&encoder, pkt_raw, length); @@ -1164,6 +1232,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) resp->length = cbor_encoder_get_buffer_size(&encoder, buf); break; case CTAP_GET_ASSERTION: + device_set_status(CTAPHID_STATUS_PROCESSING); printf1(TAG_CTAP,"CTAP_GET_ASSERTION\n"); t1 = millis(); status = ctap_get_assertion(&encoder, pkt_raw, length); @@ -1190,6 +1259,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) case CTAP_CLIENT_PIN: printf1(TAG_CTAP,"CTAP_CLIENT_PIN\n"); status = ctap_client_pin(&encoder, pkt_raw, length); + resp->length = cbor_encoder_get_buffer_size(&encoder, buf); dump_hex1(TAG_DUMP, buf, cbor_encoder_get_buffer_size(&encoder, buf)); break; @@ -1228,6 +1298,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) } done: + device_set_status(CTAPHID_STATUS_IDLE); getAssertionState.lastcmd = cmd; if (status != CTAP1_ERR_SUCCESS) @@ -1235,7 +1306,7 @@ done: resp->length = 0; } - printf1(TAG_CTAP,"cbor output structure: %d bytes\n", resp->length); + printf1(TAG_CTAP,"cbor output structure: %d bytes. Return 0x%02x\n", resp->length, status); return status; } @@ -1267,6 +1338,8 @@ void ctap_init() authenticator_read_state(&STATE); + device_set_status(CTAPHID_STATUS_IDLE); + if (STATE.is_initialized == INITIALIZED_MARKER) { printf1(TAG_STOR,"Auth state is initialized\n"); @@ -1295,7 +1368,7 @@ void ctap_init() { printf1(TAG_STOR,"pin code: \"%s\"\n", STATE.pin_code); crypto_sha256_init(); - crypto_sha256_update(STATE.pin_code, strnlen(STATE.pin_code, NEW_PIN_ENC_MAX_SIZE)); + crypto_sha256_update(STATE.pin_code, STATE.pin_code_length); crypto_sha256_final(PIN_CODE_HASH); printf1(TAG_STOR, "attempts_left: %d\n", STATE.remaining_tries); } @@ -1335,14 +1408,15 @@ uint8_t ctap_pin_matches(uint8_t * pin, int len) void ctap_update_pin(uint8_t * pin, int len) { - // TODO this should go in flash - if (len > NEW_PIN_ENC_MAX_SIZE-1 || len < 4) + if (len > NEW_PIN_ENC_MIN_SIZE || len < 4) { printf2(TAG_ERR, "Update pin fail length\n"); exit(1); } - memset(STATE.pin_code, 0, NEW_PIN_ENC_MAX_SIZE); + memset(STATE.pin_code, 0, NEW_PIN_ENC_MIN_SIZE); memmove(STATE.pin_code, pin, len); + STATE.pin_code_length = len; + STATE.pin_code[NEW_PIN_ENC_MIN_SIZE - 1] = 0; crypto_sha256_init(); crypto_sha256_update(STATE.pin_code, len); @@ -1350,18 +1424,25 @@ void ctap_update_pin(uint8_t * pin, int len) STATE.is_pin_set = 1; + authenticator_write_state(&STATE, 1); + authenticator_write_state(&STATE, 0); + printf1(TAG_CTAP, "New pin set: %s\n", STATE.pin_code); } uint8_t ctap_decrement_pin_attempts() { - if (STATE.remaining_tries > 0) + if (PIN_BOOT_ATTEMPTS_LEFT > 0) + { + PIN_BOOT_ATTEMPTS_LEFT--; + } + if (! ctap_device_locked()) { STATE.remaining_tries--; ctap_flush_state(0); printf1(TAG_CP, "ATTEMPTS left: %d\n", STATE.remaining_tries); - if (STATE.remaining_tries == 0) + if (ctap_device_locked()) { memset(PIN_TOKEN,0,sizeof(PIN_TOKEN)); memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH)); @@ -1378,7 +1459,12 @@ uint8_t ctap_decrement_pin_attempts() int8_t ctap_device_locked() { - return STATE.remaining_tries == 0; + return STATE.remaining_tries <= 0; +} + +int8_t ctap_device_boot_locked() +{ + return PIN_BOOT_ATTEMPTS_LEFT <= 0; } int8_t ctap_leftover_pin_attempts() @@ -1389,6 +1475,7 @@ int8_t ctap_leftover_pin_attempts() void ctap_reset_pin_attempts() { STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS; + PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS; ctap_flush_state(0); } diff --git a/fido2/ctap.h b/fido2/ctap.h index e594d27..8f5a16c 100644 --- a/fido2/ctap.h +++ b/fido2/ctap.h @@ -34,7 +34,8 @@ #define CTAP_VENDOR_FIRST 0x40 #define CTAP_VENDOR_LAST 0xBF -#define CTAP_AAGUID ((uint8_t*)"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff") +// AAGUID For Solo +#define CTAP_AAGUID ((uint8_t*)"\x88\x76\x63\x1b\xd4\xa0\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79") #define MC_clientDataHash 0x01 #define MC_rp 0x02 @@ -126,10 +127,14 @@ #define ALLOW_LIST_MAX_SIZE 20 #define NEW_PIN_ENC_MAX_SIZE 256 // includes NULL terminator +#define NEW_PIN_ENC_MIN_SIZE 64 +#define NEW_PIN_MAX_SIZE 64 +#define NEW_PIN_MIN_SIZE 4 -#define CTAP_RESPONSE_BUFFER_SIZE 1024 +#define CTAP_RESPONSE_BUFFER_SIZE 4096 -#define PIN_LOCKOUT_ATTEMPTS 8 +#define PIN_LOCKOUT_ATTEMPTS 8 // Number of attempts total +#define PIN_BOOT_ATTEMPTS 3 // number of attempts per boot typedef struct { @@ -198,6 +203,7 @@ typedef struct uint8_t rk; uint8_t uv; + uint8_t up; uint8_t pinAuth[16]; uint8_t pinAuthPresent; @@ -215,6 +221,7 @@ typedef struct { uint32_t paramsParsed; uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE]; + uint8_t clientDataHashPresent; struct rpId rp; @@ -222,12 +229,14 @@ typedef struct uint8_t rk; uint8_t uv; + uint8_t up; uint8_t pinAuth[16]; uint8_t pinAuthPresent; int pinProtocol; CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE]; + uint8_t allowListPresent; } CTAP_getAssertion; typedef struct @@ -281,6 +290,7 @@ uint8_t ctap_is_pin_set(); uint8_t ctap_pin_matches(uint8_t * pin, int len); void ctap_reset(); int8_t ctap_device_locked(); +int8_t ctap_device_boot_locked(); // Key storage API diff --git a/fido2/ctap_parse.c b/fido2/ctap_parse.c index b959d19..757c26a 100644 --- a/fido2/ctap_parse.c +++ b/fido2/ctap_parse.c @@ -92,7 +92,7 @@ const char * cbor_value_get_type_string(const CborValue *value) uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val) { size_t sz, map_length; - uint8_t key[8]; + uint8_t key[24]; int ret; int i; CborValue map; @@ -126,6 +126,7 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val) printf2(TAG_ERR,"Error, rp map key is too large\n"); return CTAP2_ERR_LIMIT_EXCEEDED; } + check_ret(ret); key[sizeof(key) - 1] = 0; @@ -153,6 +154,11 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val) } else if (strcmp((const char *)key, "name") == 0) { + if (cbor_value_get_type(&map) != CborTextStringType) + { + printf2(TAG_ERR,"Error, expecting text string type for user.name value\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; + } sz = USER_NAME_LIMIT; ret = cbor_value_copy_text_string(&map, (char *)MC->user.name, &sz, NULL); if (ret != CborErrorOutOfMemory) @@ -161,6 +167,22 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val) } MC->user.name[USER_NAME_LIMIT - 1] = 0; } + else if (strcmp((const char *)key, "displayName") == 0) + { + if (cbor_value_get_type(&map) != CborTextStringType) + { + printf2(TAG_ERR,"Error, expecting text string type for user.displayName value\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; + } + } + else if (strcmp((const char *)key, "icon") == 0) + { + if (cbor_value_get_type(&map) != CborTextStringType) + { + printf2(TAG_ERR,"Error, expecting text string type for user.icon value\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; + } + } else { printf1(TAG_PARSE,"ignoring key %s for user map\n", key); @@ -263,6 +285,19 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val) ret = cbor_value_get_array_length(val, &arr_length); check_ret(ret); + for (i = 0; i < arr_length; i++) + { + if ((ret = parse_pub_key_cred_param(&arr, &cred_type, &alg_type)) != 0) + { + return ret; + } + ret = cbor_value_advance(&arr); + check_ret(ret); + } + + ret = cbor_value_enter_container(val,&arr); + check_ret(ret); + for (i = 0; i < arr_length; i++) { if ((ret = parse_pub_key_cred_param(&arr, &cred_type, &alg_type)) == 0) @@ -275,11 +310,6 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val) return 0; } } - else - { - // Continue? fail? - return ret; - } ret = cbor_value_advance(&arr); check_ret(ret); } @@ -309,10 +339,40 @@ uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len) return 0; } +uint8_t parse_verify_exclude_list(CborValue * val) +{ + int i; + int ret; + CborValue arr; + size_t size; + CTAP_credentialDescriptor cred; + if (cbor_value_get_type(val) != CborArrayType) + { + printf2(TAG_ERR,"error, exclude list is not a map\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; + } + ret = cbor_value_get_array_length(val, &size); + check_ret(ret); + ret = cbor_value_enter_container(val,&arr); + check_ret(ret); + for (i = 0; i < size; i++) + { + ret = parse_credential_descriptor(&arr, &cred); + check_ret(ret); + ret = cbor_value_advance(&arr); + check_ret(ret); + + } + return 0; +} uint8_t parse_rp_id(struct rpId * rp, CborValue * val) { size_t sz = DOMAIN_NAME_MAX_SIZE; + if (cbor_value_get_type(val) != CborTextStringType) + { + return CTAP2_ERR_INVALID_CBOR_TYPE; + } int ret = cbor_value_copy_text_string(val, (char*)rp->id, &sz, NULL); if (ret == CborErrorOutOfMemory) { @@ -413,7 +473,7 @@ uint8_t parse_rp(struct rpId * rp, CborValue * val) return 0; } -uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv) +uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up) { size_t sz, map_length; char key[8]; @@ -463,21 +523,27 @@ uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv) return CTAP2_ERR_INVALID_CBOR_TYPE; } - if (strcmp(key, "rk") == 0) + if (strncmp(key, "rk",2) == 0) { ret = cbor_value_get_boolean(&map, &b); check_ret(ret); *rk = b; } - else if (strcmp(key, "uv") == 0) + else if (strncmp(key, "uv",2) == 0) { ret = cbor_value_get_boolean(&map, &b); check_ret(ret); *uv = b; } + else if (strncmp(key, "up",2) == 0) + { + ret = cbor_value_get_boolean(&map, &b); + check_ret(ret); + *up = b; + } else { - printf1(TAG_PARSE,"ignoring key %s for option map\n", key); + printf2(TAG_PARSE,"ignoring option specified %s\n", key); } @@ -576,27 +642,30 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod break; case MC_excludeList: printf1(TAG_MC,"CTAP_excludeList\n"); - if( cbor_value_get_type(&map) == CborArrayType ) - { - ret = cbor_value_enter_container(&map, &MC->excludeList); - check_ret(ret); + ret = parse_verify_exclude_list(&map); + check_ret(ret); + + ret = cbor_value_enter_container(&map, &MC->excludeList); + check_ret(ret); + + ret = cbor_value_get_array_length(&map, &MC->excludeListSize); + check_ret(ret); + - ret = cbor_value_get_array_length(&map, &MC->excludeListSize); - check_ret(ret); - } - else - { - return CTAP2_ERR_INVALID_CBOR_TYPE; - } printf1(TAG_MC,"CTAP_excludeList done\n"); break; case MC_extensions: printf1(TAG_MC,"CTAP_extensions\n"); + type = cbor_value_get_type(&map); + if (type != CborMapType) + { + return CTAP2_ERR_INVALID_CBOR_TYPE; + } break; case MC_options: printf1(TAG_MC,"CTAP_options\n"); - ret = parse_options(&map, &MC->rk, &MC->uv); + ret = parse_options(&map, &MC->rk, &MC->uv, &MC->up); check_retr(ret); break; case MC_pinAuth: @@ -661,8 +730,8 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * cbor_value_copy_byte_string(&val, (uint8_t*)&cred->credential, &buflen, NULL); if (buflen != CREDENTIAL_ID_SIZE) { - printf2(TAG_ERR,"Error, credential is incorrect length\n"); - return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; // maybe just skip it instead of fail? + printf2(TAG_ERR,"Ignoring credential is incorrect length\n"); + //return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; // maybe just skip it instead of fail? } ret = cbor_value_map_find_value(arr, "type", &val); @@ -677,13 +746,14 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * buflen = sizeof(type); cbor_value_copy_text_string(&val, type, &buflen, NULL); - if (strcmp(type, "public-key") == 0) + if (strncmp(type, "public-key",11) == 0) { cred->type = PUB_KEY_CRED_PUB_KEY; } else { cred->type = PUB_KEY_CRED_UNKNOWN; + printf1(TAG_RED, "Unknown type: %s\r\n", type); } return 0; @@ -783,6 +853,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int ret = parse_fixed_byte_string(&map, GA->clientDataHash, CLIENT_DATA_HASH_SIZE); check_retr(ret); + GA->clientDataHashPresent = 1; printf1(TAG_GA," "); dump_hex1(TAG_GA, GA->clientDataHash, 32); break; @@ -796,10 +867,9 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int case GA_allowList: printf1(TAG_GA,"GA_allowList\n"); ret = parse_allow_list(GA, &map); - if (ret == 0) - { + check_ret(ret); + GA->allowListPresent = 1; - } break; case GA_extensions: printf1(TAG_GA,"GA_extensions\n"); @@ -807,7 +877,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int case GA_options: printf1(TAG_GA,"CTAP_options\n"); - ret = parse_options(&map, &GA->rk, &GA->uv); + ret = parse_options(&map, &GA->rk, &GA->uv, &GA->up); check_retr(ret); break; case GA_pinAuth: @@ -1033,10 +1103,11 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length { ret = cbor_value_calculate_string_length(&map, &sz); check_ret(ret); - if (sz > NEW_PIN_ENC_MAX_SIZE) + if (sz > NEW_PIN_ENC_MAX_SIZE || sz < NEW_PIN_ENC_MIN_SIZE) { - return CTAP1_ERR_OTHER; + return CTAP2_ERR_PIN_POLICY_VIOLATION; } + CP->newPinEncSize = sz; sz = NEW_PIN_ENC_MAX_SIZE; ret = cbor_value_copy_byte_string(&map, CP->newPinEnc, &sz, NULL); @@ -1078,5 +1149,3 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length return 0; } - - diff --git a/fido2/ctap_parse.h b/fido2/ctap_parse.h index c5f011f..12d814d 100644 --- a/fido2/ctap_parse.h +++ b/fido2/ctap_parse.h @@ -42,7 +42,7 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val); uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len); uint8_t parse_rp_id(struct rpId * rp, CborValue * val); uint8_t parse_rp(struct rpId * rp, CborValue * val); -uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv); +uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up); uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it); uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int * crv); diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 8d4af1b..46d5523 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -43,6 +43,8 @@ typedef enum EMPTY = 0, BUFFERING, BUFFERED, + HID_ERROR, + HID_IGNORE, } CTAP_BUFFER_STATE; @@ -341,7 +343,7 @@ static void send_init_response(uint32_t oldcid, uint32_t newcid, uint8_t * nonce memmove(init_resp.nonce, nonce, 8); init_resp.cid = newcid; - init_resp.protocol_version = 0;//? + init_resp.protocol_version = CTAPHID_PROTOCOL_VERSION; init_resp.version_major = 0;//? init_resp.version_minor = 0;//? init_resp.build_version = 0;//? @@ -367,8 +369,21 @@ void ctaphid_check_timeouts() } +void ctaphid_update_status(int8_t status) +{ + CTAPHID_WRITE_BUFFER wb; + printf1(TAG_HID, "Send device update %d!\n",status); + ctaphid_write_buffer_init(&wb); -void ctaphid_handle_packet(uint8_t * pkt_raw) + wb.cid = buffer_cid(); + wb.cmd = CTAPHID_KEEPALIVE; + wb.bcnt = 1; + + ctaphid_write(&wb, &status, 1); + ctaphid_write(&wb, NULL, 0); +} + +static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * cid, int * len) { CTAPHID_PACKET * pkt = (CTAPHID_PACKET *)(pkt_raw); @@ -378,29 +393,25 @@ void ctaphid_handle_packet(uint8_t * pkt_raw) if (!is_cont_pkt(pkt)) printf1(TAG_HID, " length: %d\n", ctaphid_packet_len(pkt)); int ret; - uint8_t status; uint32_t oldcid; uint32_t newcid; - static CTAPHID_WRITE_BUFFER wb; - uint32_t active_cid; - uint32_t t1,t2; - CTAP_RESPONSE ctap_resp; + *cid = pkt->cid; if (is_init_pkt(pkt)) { if (ctaphid_packet_len(pkt) != 8) { printf2(TAG_ERR, "Error,invalid length field for init packet\n"); - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH); - return; + *cmd = CTAP1_ERR_INVALID_LENGTH; + return HID_ERROR; } if (pkt->cid == 0) { printf2(TAG_ERR,"Error, invalid cid 0\n"); - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_CHANNEL); - return; + *cmd = CTAP1_ERR_INVALID_CHANNEL; + return HID_ERROR; } ctaphid_init(); @@ -426,21 +437,21 @@ void ctaphid_handle_packet(uint8_t * pkt_raw) if (ret == -1) { printf2(TAG_ERR, "Error, not enough memory for new CID. return BUSY.\n"); - ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY); - return; + *cmd = CTAP1_ERR_CHANNEL_BUSY; + return HID_ERROR; } send_init_response(oldcid, newcid, pkt->pkt.init.payload); cid_del(newcid); - return; + return HID_IGNORE; } else { // Check if matches existing CID if (pkt->cid == CTAPHID_BROADCAST_CID) { - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_CHANNEL); - return; + *cmd = CTAP1_ERR_INVALID_CHANNEL; + return HID_ERROR; } if (cid_exists(pkt->cid)) { @@ -450,14 +461,14 @@ void ctaphid_handle_packet(uint8_t * pkt_raw) { printf2(TAG_ERR,"INVALID_SEQ\n"); printf2(TAG_ERR,"Have %d/%d bytes\n", ctap_buffer_offset, ctap_buffer_bcnt); - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_SEQ); - return; + *cmd = CTAP1_ERR_INVALID_SEQ; + return HID_ERROR; } else if (pkt->cid != buffer_cid()) { printf2(TAG_ERR,"BUSY with %08x\n", buffer_cid()); - ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY); - return; + *cmd = CTAP1_ERR_CHANNEL_BUSY; + return HID_ERROR; } } if (! is_cont_pkt(pkt)) @@ -465,8 +476,8 @@ void ctaphid_handle_packet(uint8_t * pkt_raw) if (ctaphid_packet_len(pkt) > CTAPHID_BUFFER_SIZE) { - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH); - return; + *cmd = CTAP1_ERR_INVALID_LENGTH; + return HID_ERROR; } } else @@ -474,14 +485,14 @@ void ctaphid_handle_packet(uint8_t * pkt_raw) if (buffer_status() == EMPTY || pkt->cid != buffer_cid()) { printf2(TAG_ERR,"ignoring random cont packet\n"); - return; + return HID_IGNORE; } } if (buffer_packet(pkt) == SEQUENCE_ERROR) { printf2(TAG_ERR,"Buffering sequence error\n"); - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_SEQ); - return; + *cmd = CTAP1_ERR_INVALID_SEQ; + return HID_ERROR; } ret = cid_refresh(pkt->cid); if (ret != 0) @@ -489,133 +500,174 @@ void ctaphid_handle_packet(uint8_t * pkt_raw) printf2(TAG_ERR,"Error, refresh cid failed\n"); exit(1); } - active_cid = pkt->cid; } else if (is_cont_pkt(pkt)) { printf2(TAG_ERR,"ignoring unwarranted cont packet\n"); + // Ignore - return; + return HID_IGNORE; } else { printf2(TAG_ERR,"BUSY\n"); - ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY); - return; + *cmd = CTAP1_ERR_CHANNEL_BUSY; + return HID_ERROR; } } - - - switch(buffer_status()) - { - case BUFFERING: - printf1(TAG_HID,"BUFFERING\n"); - active_cid_timestamp = millis(); - break; - - case EMPTY: - printf1(TAG_HID,"empty buffer!\n"); - case BUFFERED: - switch(buffer_cmd()) - { - - case CTAPHID_INIT: - printf2(TAG_ERR,"CTAPHID_INIT, error this should already be handled\n"); - exit(1); - break; -#ifndef DISABLE_CTAPHID_PING - case CTAPHID_PING: - printf1(TAG_HID,"CTAPHID_PING\n"); - - ctaphid_write_buffer_init(&wb); - wb.cid = active_cid; - wb.cmd = CTAPHID_PING; - wb.bcnt = buffer_len(); - t1 = millis(); - ctaphid_write(&wb, ctap_buffer, buffer_len()); - ctaphid_write(&wb, NULL,0); - t2 = millis(); - printf1(TAG_TIME,"PING writeback: %d ms\n",(uint32_t)(t2-t1)); - break; -#endif -#ifndef DISABLE_CTAPHID_WINK - case CTAPHID_WINK: - printf1(TAG_HID,"CTAPHID_WINK\n"); - - ctaphid_write_buffer_init(&wb); - - wb.cid = active_cid; - wb.cmd = CTAPHID_WINK; - - ctaphid_write(&wb,NULL,0); - - break; -#endif -#ifndef DISABLE_CTAPHID_CBOR - case CTAPHID_CBOR: - printf1(TAG_HID,"CTAPHID_CBOR\n"); - if (buffer_len() == 0) - { - printf2(TAG_ERR,"Error,invalid 0 length field for cbor packet\n"); - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH); - return; - } - - ctap_response_init(&ctap_resp); - status = ctap_request(ctap_buffer, buffer_len(), &ctap_resp); - - ctaphid_write_buffer_init(&wb); - wb.cid = active_cid; - wb.cmd = CTAPHID_CBOR; - wb.bcnt = (ctap_resp.length+1); - - - t1 = millis(); - ctaphid_write(&wb, &status, 1); - ctaphid_write(&wb, ctap_resp.data, ctap_resp.length); - ctaphid_write(&wb, NULL, 0); - t2 = millis(); - printf1(TAG_TIME,"CBOR writeback: %d ms\n",(uint32_t)(t2-t1)); - break; -#endif - case CTAPHID_MSG: - printf1(TAG_HID,"CTAPHID_MSG\n"); - if (buffer_len() == 0) - { - printf2(TAG_ERR,"Error,invalid 0 length field for MSG/U2F packet\n"); - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH); - return; - } - - ctap_response_init(&ctap_resp); - u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp); - - ctaphid_write_buffer_init(&wb); - wb.cid = active_cid; - wb.cmd = CTAPHID_MSG; - wb.bcnt = (ctap_resp.length); - - ctaphid_write(&wb, ctap_resp.data, ctap_resp.length); - ctaphid_write(&wb, NULL, 0); - break; - - default: - printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); - ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_COMMAND); - break; - } - cid_del(buffer_cid()); - buffer_reset(); - break; - - default: - printf2(TAG_ERR,"invalid buffer state; abort\n"); - exit(1); - break; - } - - printf1(TAG_HID,"\n"); - + *len = buffer_len(); + *cmd = buffer_cmd(); + return buffer_status(); } +uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) +{ + uint8_t cmd; + uint32_t cid; + int len; + int status; + + static uint8_t is_busy = 0; + static CTAPHID_WRITE_BUFFER wb; + CTAP_RESPONSE ctap_resp; + + uint32_t t1,t2; + + int bufstatus = ctaphid_buffer_packet(pkt_raw, &cmd, &cid, &len); + + if (bufstatus == HID_IGNORE) + { + return 0; + } + + if (bufstatus == HID_ERROR) + { + cid_del(cid); + buffer_reset(); + ctaphid_send_error(cid, cmd); + return 0; + } + + if (bufstatus == BUFFERING) + { + active_cid_timestamp = millis(); + return 0; + } + + + switch(cmd) + { + + case CTAPHID_INIT: + printf2(TAG_ERR,"CTAPHID_INIT, error this should already be handled\n"); + exit(1); + break; +#ifndef DISABLE_CTAPHID_PING + case CTAPHID_PING: + printf1(TAG_HID,"CTAPHID_PING\n"); + + ctaphid_write_buffer_init(&wb); + wb.cid = cid; + wb.cmd = CTAPHID_PING; + wb.bcnt = len; + t1 = millis(); + ctaphid_write(&wb, ctap_buffer, len); + ctaphid_write(&wb, NULL,0); + t2 = millis(); + printf1(TAG_TIME,"PING writeback: %d ms\n",(uint32_t)(t2-t1)); + break; +#endif +#ifndef DISABLE_CTAPHID_WINK + case CTAPHID_WINK: + printf1(TAG_HID,"CTAPHID_WINK\n"); + + ctaphid_write_buffer_init(&wb); + + wb.cid = cid; + wb.cmd = CTAPHID_WINK; + + ctaphid_write(&wb,NULL,0); + + break; +#endif +#ifndef DISABLE_CTAPHID_CBOR + case CTAPHID_CBOR: + printf1(TAG_HID,"CTAPHID_CBOR\n"); + + if (len == 0) + { + printf2(TAG_ERR,"Error,invalid 0 length field for cbor packet\n"); + ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH); + return 0; + } + if (is_busy) + { + printf1(TAG_HID,"Channel busy for CBOR\n"); + ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY); + return 0; + } + is_busy = 1; + ctap_response_init(&ctap_resp); + status = ctap_request(ctap_buffer, len, &ctap_resp); + + ctaphid_write_buffer_init(&wb); + wb.cid = cid; + wb.cmd = CTAPHID_CBOR; + wb.bcnt = (ctap_resp.length+1); + + + t1 = millis(); + ctaphid_write(&wb, &status, 1); + ctaphid_write(&wb, ctap_resp.data, ctap_resp.length); + ctaphid_write(&wb, NULL, 0); + t2 = millis(); + printf1(TAG_TIME,"CBOR writeback: %d ms\n",(uint32_t)(t2-t1)); + is_busy = 0; + break; +#endif + case CTAPHID_MSG: + + printf1(TAG_HID,"CTAPHID_MSG\n"); + if (len == 0) + { + printf2(TAG_ERR,"Error,invalid 0 length field for MSG/U2F packet\n"); + ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH); + return 0; + } + if (is_busy) + { + printf1(TAG_HID,"Channel busy for MSG\n"); + ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY); + return 0; + } + is_busy = 1; + ctap_response_init(&ctap_resp); + u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp); + + ctaphid_write_buffer_init(&wb); + wb.cid = cid; + wb.cmd = CTAPHID_MSG; + wb.bcnt = (ctap_resp.length); + + ctaphid_write(&wb, ctap_resp.data, ctap_resp.length); + ctaphid_write(&wb, NULL, 0); + is_busy = 0; + break; + case CTAPHID_CANCEL: + printf1(TAG_HID,"CTAPHID_CANCEL\n"); + is_busy = 0; + break; + default: + printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); + ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND); + break; + } + cid_del(cid); + buffer_reset(); + + printf1(TAG_HID,"\n"); + if (!is_busy) return cmd; + else return 0; + +} diff --git a/fido2/ctaphid.h b/fido2/ctaphid.h index a141864..f0e5bf5 100644 --- a/fido2/ctaphid.h +++ b/fido2/ctaphid.h @@ -36,6 +36,7 @@ #define CTAPHID_CBOR (TYPE_INIT | 0x10) #define CTAPHID_CANCEL (TYPE_INIT | 0x11) #define CTAPHID_ERROR (TYPE_INIT | 0x3f) +#define CTAPHID_KEEPALIVE (TYPE_INIT | 0x3b) #define ERR_INVALID_CMD 0x01 #define ERR_INVALID_PAR 0x02 @@ -43,6 +44,11 @@ #define ERR_MSG_TIMEOUT 0x05 #define ERR_CHANNEL_BUSY 0x06 +#define CTAPHID_PROTOCOL_VERSION 2 + +#define CTAPHID_STATUS_IDLE 0 +#define CTAPHID_STATUS_PROCESSING 1 +#define CTAPHID_STATUS_UPNEEDED 2 #define CTAPHID_INIT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-7) #define CTAPHID_CONT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-5) @@ -91,10 +97,12 @@ typedef struct void ctaphid_init(); -void ctaphid_handle_packet(uint8_t * pkt_raw); +uint8_t ctaphid_handle_packet(uint8_t * pkt_raw); void ctaphid_check_timeouts(); +void ctaphid_update_status(int8_t status); + #define ctaphid_packet_len(pkt) ((uint16_t)((pkt)->pkt.init.bcnth << 8) | ((pkt)->pkt.init.bcntl)) diff --git a/fido2/device.h b/fido2/device.h index a49391c..adbc842 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -56,8 +56,12 @@ void authenticator_write_state(AuthenticatorState *, int backup); // Called each main loop. Doesn't need to do anything. void device_manage(); +// sets status that's uses for sending status updates ~100ms. +// A timer should be set up to call `ctaphid_update_status` +void device_set_status(int status); + // Test for user presence -// Return 1 for user is present, 0 user not present +// Return 1 for user is present, 0 user not present, -1 if cancel is requested. extern int ctap_user_presence_test(); // Generate @num bytes of random numbers to @dest diff --git a/fido2/main.c b/fido2/main.c index a2cca61..797c856 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -45,20 +45,20 @@ int main(int argc, char * argv[]) set_logging_mask( /*0*/ - TAG_GEN| - /*TAG_MC |*/ - /*TAG_GA |*/ - TAG_WALLET | + // TAG_GEN| + // TAG_MC | + // TAG_GA | + // TAG_WALLET | TAG_STOR | - /*TAG_CP |*/ + // TAG_CP | TAG_CTAP| -// TAG_HID| + // TAG_HID| /*TAG_U2F|*/ - /*TAG_PARSE |*/ -// TAG_TIME| - /*TAG_DUMP|*/ - /*TAG_GREEN|*/ - /*TAG_RED|*/ + // TAG_PARSE | + //TAG_TIME| + // TAG_DUMP| + TAG_GREEN| + TAG_RED| TAG_ERR ); @@ -89,12 +89,11 @@ int main(int argc, char * argv[]) if (usbhid_recv(hidmsg) > 0) { - printf1(TAG_DUMP,"%d>> ",count++); dump_hex1(TAG_DUMP, hidmsg,sizeof(hidmsg)); t2 = millis(); ctaphid_handle_packet(hidmsg); accum += millis() - t2; - printf1(TAG_TIME,"accum: %d\n", (uint32_t)accum); - printf1(TAG_TIME,"dt: %d\n", t2 - dt); + // printf1(TAG_TIME,"accum: %d\n", (uint32_t)accum); + // printf1(TAG_TIME,"dt: %d\n", t2 - dt); dt = t2; memset(hidmsg, 0, sizeof(hidmsg)); } diff --git a/fido2/storage.h b/fido2/storage.h index c9b5bbe..aafde2d 100644 --- a/fido2/storage.h +++ b/fido2/storage.h @@ -39,8 +39,9 @@ typedef struct // Pin information uint8_t is_initialized; uint8_t is_pin_set; - uint8_t pin_code[NEW_PIN_ENC_MAX_SIZE]; - uint8_t remaining_tries; + uint8_t pin_code[NEW_PIN_ENC_MIN_SIZE]; + int pin_code_length; + int8_t remaining_tries; uint16_t key_lens[MAX_KEYS]; uint8_t key_space[KEY_SPACE_BYTES]; diff --git a/targets/stm32l442/Makefile b/targets/stm32l442/Makefile index f4f59d3..55802c1 100644 --- a/targets/stm32l442/Makefile +++ b/targets/stm32l442/Makefile @@ -40,6 +40,7 @@ HW=-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb CHIP=STM32L442xx DEFINES = -D$(CHIP) -DAES256=1 -DUSE_FULL_LL_DRIVER +# DEFINES += -DTEST_SOLO_STM32 -DTEST -DTEST_FIFO=1 CFLAGS=$(INC) -c $(DEFINES) -Os -Wall -fdata-sections -ffunction-sections $(HW) LDFLAGS_LIB=$(HW) $(SEARCH) -specs=nano.specs -specs=nosys.specs -Wl,--gc-sections -u _printf_float -lnosys @@ -68,7 +69,8 @@ clean: rm -f *.o src/*.o src/*.elf *.elf *.hex $(OBJ) flash: $(TARGET).hex - STM32_Programmer_CLI -c port=SWD -halt -d $(TARGET).hex -rst + STM32_Programmer_CLI -c port=SWD -halt -e all + STM32_Programmer_CLI -c port=SWD -halt -d $(TARGET).hex -rst sleep 0.5 python dfuse-tool/dfuse-tool.py --leave diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index ed56c79..f4ecb7f 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -15,6 +15,7 @@ #include "util.h" #include "fifo.h" #include "log.h" +#include "ctaphid.h" #define PAGE_SIZE 2048 @@ -34,18 +35,28 @@ #define AUTH_WORD_ADDR (flash_addr(APPLICATION_END_PAGE)-4) -uint32_t __65_seconds = 0; +uint32_t __90_ms = CTAPHID_STATUS_IDLE; +uint32_t __device_status = 0; +uint32_t __last_update = 0; extern PCD_HandleTypeDef hpcd; #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) -// Timer6 overflow handler +// Timer6 overflow handler. happens every ~90ms. void TIM6_DAC_IRQHandler() { // timer is only 16 bits, so roll it over here TIM6->SR = 0; - __65_seconds += 1; + __90_ms += 1; + if ((millis() - __last_update) > 5) + { + if (__device_status != CTAPHID_STATUS_IDLE) + { + ctaphid_update_status(__device_status); + } + } } + // Global USB interrupt handler void USB_IRQHandler(void) { @@ -55,10 +66,21 @@ void USB_IRQHandler(void) uint32_t millis() { - return (((uint32_t)TIM6->CNT) | (__65_seconds<<16)); + return (((uint32_t)TIM6->CNT) + (__90_ms * 90)); } +void device_set_status(int status) +{ + __disable_irq(); + __last_update = millis(); + __enable_irq(); + if (status != CTAPHID_STATUS_IDLE && __device_status != status) + { + ctaphid_update_status(status); + } + __device_status = status; +} void delay(uint32_t ms) @@ -75,7 +97,6 @@ void device_init() LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); printf1(TAG_GEN,"hello solo\r\n"); - } void usbhid_init() @@ -86,7 +107,6 @@ int usbhid_recv(uint8_t * msg) { if (fifo_hidmsg_size()) { - fifo_hidmsg_take(msg); printf1(TAG_DUMP,">> "); dump_hex1(TAG_DUMP,msg, HID_PACKET_SIZE); @@ -188,9 +208,11 @@ uint32_t ctap_atomic_count(int sel) int offset = 0; uint32_t * ptr = (uint32_t *)flash_addr(COUNTER1_PAGE); uint32_t erases = *(uint32_t *)flash_addr(COUNTER2_PAGE); + static uint32_t sc = 0; if (erases == 0xffffffff) { erases = 1; + flash_erase_page(COUNTER2_PAGE); flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); } @@ -220,44 +242,54 @@ uint32_t ctap_atomic_count(int sel) if (!lastc) // Happens on initialization as well. { - printf("warning, power interrupted during previous count. Restoring.\r\n"); + printf2(TAG_ERR,"warning, power interrupted during previous count. Restoring. lastc==%lu, erases=%lu, offset=%d\r\n", lastc,erases,offset); // there are 32 counts per page - lastc = erases * 32; + lastc = erases * 256 + 1; flash_erase_page(COUNTER1_PAGE); flash_write(flash_addr(COUNTER1_PAGE), (uint8_t*)&lastc, 4); erases++; flash_erase_page(COUNTER2_PAGE); flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); + return lastc; } lastc++; - if (lastc/32 > erases) + if (lastc/256 > erases) { - printf("warning, power interrupted, erases mark, restoring\r\n"); - erases = lastc/32 + 1; + printf2(TAG_ERR,"warning, power interrupted, erases mark, restoring. lastc==%lu, erases=%lu\r\n", lastc,erases); + erases = lastc/256; flash_erase_page(COUNTER2_PAGE); flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); } if (offset == PAGE_SIZE/4) { - if (lastc/32 > erases) + if (lastc/256 > erases) { - printf("warning, power interrupted, erases mark, restoring\r\n"); + printf2(TAG_ERR,"warning, power interrupted, erases mark, restoring lastc==%lu, erases=%lu\r\n", lastc,erases); } - erases = lastc/32 + 1; + erases = lastc/256 + 1; flash_erase_page(COUNTER2_PAGE); flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4); flash_erase_page(COUNTER1_PAGE); + offset = 0; } - else + + + flash_write(flash_addr(COUNTER1_PAGE) + offset * 4, (uint8_t*)&lastc, 4); + + if (lastc == sc) { - flash_write(flash_addr(COUNTER1_PAGE) + offset * 4, (uint8_t*)&lastc, 4); + printf1(TAG_RED,"no count detected: lastc==%lu, erases=%lu, offset=%d\r\n", lastc,erases,offset); + while(1) + ; } + sc = lastc; + return lastc; } @@ -284,10 +316,38 @@ void device_manage() #endif } +static int handle_packets() +{ + static uint8_t hidmsg[HID_PACKET_SIZE]; + memset(hidmsg,0, sizeof(hidmsg)); + if (usbhid_recv(hidmsg) > 0) + { + if ( ctaphid_handle_packet(hidmsg) == CTAPHID_CANCEL) + { + printf1(TAG_GREEN, "CANCEL!\r\n"); + return -1; + } + else + { + return 0; + } + } + return 0; +} + int ctap_user_presence_test() { + int oldstatus = __device_status; + int ret; #if SKIP_BUTTON_CHECK - return 1; + int i=500; + while(i--) + { + delay(1); + ret = handle_packets(); + if (ret) return ret; + } + goto done; #endif uint32_t t1 = millis(); @@ -297,15 +357,17 @@ int ctap_user_presence_test() delay(3000); led_rgb(0x001040); delay(50); - return 1; + goto done; #endif while (IS_BUTTON_PRESSED()) { if (t1 + 5000 < millis()) { printf1(TAG_GEN,"Button not pressed\n"); - return 0; + goto fail; } + ret = handle_packets(); + if (ret) return ret; } t1 = millis(); @@ -314,11 +376,13 @@ do { if (t1 + 5000 < millis()) { - return 0; + goto fail; } if (! IS_BUTTON_PRESSED()) continue; delay(1); + ret = handle_packets(); + if (ret) return ret; } while (! IS_BUTTON_PRESSED()); @@ -326,7 +390,11 @@ led_rgb(0x001040); delay(50); +done: return 1; + +fail: +return 0; } int ctap_generate_rng(uint8_t * dst, size_t num) diff --git a/targets/stm32l442/src/fifo.c b/targets/stm32l442/src/fifo.c index c8f621e..cd13348 100644 --- a/targets/stm32l442/src/fifo.c +++ b/targets/stm32l442/src/fifo.c @@ -6,7 +6,7 @@ FIFO_CREATE(debug,1024,1) -FIFO_CREATE(hidmsg,100,100) +FIFO_CREATE(hidmsg,100,64) #if TEST_FIFO FIFO_CREATE(test,10,100) @@ -24,23 +24,25 @@ void fifo_test() for (int i = 0; i < 10; i++) { + printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead()); ret = fifo_test_add(data[i]); printf("%d\r\n",i); if (ret != 0) { printf("fifo_test_add fail\r\n"); - goto end; + goto fail; } } for (int i = 0; i < 10; i++) { + printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead()); ret = fifo_test_take(verif[i]); printf("%d\r\n",i ); if (ret != 0) { printf("fifo_test_take fail\r\n"); - goto end; + goto fail; } if (memcmp(verif[i], data[i], 100) != 0) @@ -48,17 +50,18 @@ void fifo_test() printf("fifo_test_take result fail\r\n"); dump_hex(data[i],100); dump_hex(verif[i],100); - goto end; + goto fail; } } for (int i = 0; i < 10; i++) { + printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead()); ret = fifo_test_add(data[i]); if (ret != 0) { printf("fifo_test_add 2 fail\r\n"); - goto end; + goto fail; } } @@ -66,22 +69,25 @@ void fifo_test() if (ret == 0) { printf("fifo_test_add should have failed\r\n"); - goto end; + goto fail; } + + for (int i = 0; i < 10; i++) { + printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead()); ret = fifo_test_take(verif[i]); if (ret != 0) { printf("fifo_test_take fail\r\n"); - goto end; + goto fail; } if (memcmp(verif[i], data[i], 100) != 0) { printf("fifo_test_take result fail\r\n"); - goto end; + goto fail; } } @@ -89,12 +95,12 @@ void fifo_test() if (ret == 0) { printf("fifo_test_take should have failed\r\n"); - goto end; + goto fail; } printf("test pass!\r\n"); - - end: + return ; + fail: while(1) ; } diff --git a/targets/stm32l442/src/fifo.h b/targets/stm32l442/src/fifo.h index 31efa95..115e04f 100644 --- a/targets/stm32l442/src/fifo.h +++ b/targets/stm32l442/src/fifo.h @@ -3,7 +3,9 @@ #include "app.h" +#ifndef TEST_FIFO #define TEST_FIFO 0 +#endif #define FIFO_CREATE(NAME,LENGTH,BYTES)\ int __##NAME##_WRITE_PTR = 0;\ @@ -13,7 +15,7 @@ static uint8_t __##NAME##_WRITE_BUF[BYTES * LENGTH];\ \ int fifo_##NAME##_add(uint8_t * c)\ {\ - if (__##NAME##_WRITE_PTR != __##NAME##_READ_PTR || !__##NAME##_SIZE)\ + if (__##NAME##_SIZE < LENGTH)\ {\ memmove(__##NAME##_WRITE_BUF + __##NAME##_WRITE_PTR * BYTES, c, BYTES);\ __##NAME##_WRITE_PTR ++;\ @@ -28,7 +30,7 @@ int fifo_##NAME##_add(uint8_t * c)\ int fifo_##NAME##_take(uint8_t * c)\ {\ memmove(c, __##NAME##_WRITE_BUF + __##NAME##_READ_PTR * BYTES, BYTES);\ - if (__##NAME##_READ_PTR != __##NAME##_WRITE_PTR || __##NAME##_SIZE)\ + if ( __##NAME##_SIZE > 0)\ {\ __##NAME##_READ_PTR ++;\ if (__##NAME##_READ_PTR >= LENGTH)\ @@ -43,17 +45,27 @@ uint32_t fifo_##NAME##_size()\ {\ return (__##NAME##_SIZE);\ }\ +uint32_t fifo_##NAME##_rhead()\ +{\ + return (__##NAME##_READ_PTR);\ +}\ +uint32_t fifo_##NAME##_whead()\ +{\ + return (__##NAME##_WRITE_PTR);\ +}\ -#define FIFO_CREATE_H(NAME,LENGTH,BYTES)\ +#define FIFO_CREATE_H(NAME)\ int fifo_##NAME##_add(uint8_t * c);\ int fifo_##NAME##_take(uint8_t * c);\ uint32_t fifo_##NAME##_size();\ +uint32_t fifo_##NAME##_rhead();\ +uint32_t fifo_##NAME##_whead();\ -FIFO_CREATE_H(hidmsg,10,64) +FIFO_CREATE_H(hidmsg) -FIFO_CREATE_H(debug,1024,1) +FIFO_CREATE_H(debug) -FIFO_CREATE_H(test,100,100) +FIFO_CREATE_H(test) void fifo_test(); diff --git a/targets/stm32l442/src/flash.c b/targets/stm32l442/src/flash.c index b86ef87..d87a002 100644 --- a/targets/stm32l442/src/flash.c +++ b/targets/stm32l442/src/flash.c @@ -18,6 +18,7 @@ static void flash_unlock() void flash_erase_page(uint8_t page) { __disable_irq(); + flash_unlock(); // Wait if flash is busy while (FLASH->SR & (1<<16)) ; @@ -71,9 +72,10 @@ void flash_write(uint32_t addr, uint8_t * data, size_t sz) { int i; uint8_t buf[8]; + flash_unlock(); // dword align - addr &= ~(0x7); + addr &= ~(0x07); for(i = 0; i < sz; i+=8) { diff --git a/targets/stm32l442/src/init.c b/targets/stm32l442/src/init.c index 62d5a19..dc7e498 100644 --- a/targets/stm32l442/src/init.c +++ b/targets/stm32l442/src/init.c @@ -337,10 +337,10 @@ static void MX_TIM6_Init(void) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6); // 48 MHz sys clock --> 6 MHz timer clock - // 6 MHz / 6000 == 1000 Hz + // 48 MHz / 48000 == 1000 Hz TIM_InitStruct.Prescaler = 48000; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; - TIM_InitStruct.Autoreload = 0xffff; + TIM_InitStruct.Autoreload = 90; LL_TIM_Init(TIM6, &TIM_InitStruct); LL_TIM_DisableARRPreload(TIM6); @@ -356,6 +356,35 @@ static void MX_TIM6_Init(void) LL_TIM_EnableCounter(TIM6); } +/* TIM7 init function */ +// static void MX_TIM7_Init(void) +// { +// +// LL_TIM_InitTypeDef TIM_InitStruct; +// +// /* Peripheral clock enable */ +// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7); +// +// // 48 MHz sys clock --> 6 MHz timer clock +// // 6 MHz / 6000 == 1000 Hz +// TIM_InitStruct.Prescaler = 48000; +// TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; +// TIM_InitStruct.Autoreload = 0xffff; +// LL_TIM_Init(TIM6, &TIM_InitStruct); +// +// LL_TIM_DisableARRPreload(TIM7); +// +// LL_TIM_SetTriggerOutput(TIM7, LL_TIM_TRGO_RESET); +// +// LL_TIM_DisableMasterSlaveMode(TIM7); +// +// // enable interrupt +// TIM7->DIER |= 1; +// +// // Start immediately +// LL_TIM_EnableCounter(TIM7); +// } + /* RNG init function */ static void MX_RNG_Init(void) { diff --git a/targets/stm32l442/src/main.c b/targets/stm32l442/src/main.c index 1aef4a3..87cbe4d 100644 --- a/targets/stm32l442/src/main.c +++ b/targets/stm32l442/src/main.c @@ -27,9 +27,126 @@ #include "device.h" #include "util.h" #include "fifo.h" +#include "log.h" #ifdef TEST_SOLO_STM32 #define Error_Handler() _Error_Handler(__FILE__,__LINE__) +#define PAGE_SIZE 2048 +#define PAGES 128 +// Pages 119-127 are data +#define COUNTER2_PAGE (PAGES - 4) +#define COUNTER1_PAGE (PAGES - 3) +#define STATE2_PAGE (PAGES - 2) +#define STATE1_PAGE (PAGES - 1) + +void test_atomic_counter() +{ + // flash_erase_page(COUNTER1_PAGE); + // flash_erase_page(COUNTER2_PAGE); + int i; + uint32_t c0 = ctap_atomic_count(0); + for (i = 0; i < 128; i++) + { + uint32_t c1 = ctap_atomic_count(0); + if (c1 <= (c0 )) + { + printf("error, count failed %lu <= %lu\r\n",c1,c0); + while(1) + ; + } + printf("%lu\r\n", c1); + c0 = c1; + } + + printf("test faults\r\n"); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER1_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER1_PAGE); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER1_PAGE); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER1_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER2_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER2_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER2_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER2_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER1_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER1_PAGE); + + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + printf("%lu\r\n", ctap_atomic_count(0)); + + flash_erase_page(COUNTER1_PAGE); + +} int main(void) { @@ -41,7 +158,24 @@ int main(void) uint8_t hidbuf[HID_PACKET_SIZE]; hw_init(); - + set_logging_mask( + /*0*/ + // TAG_GEN| + TAG_MC | + TAG_GA | + // TAG_WALLET | + TAG_STOR | + TAG_CP | + TAG_CTAP| +// TAG_HID| + /*TAG_U2F|*/ + TAG_PARSE | + //TAG_TIME| + // TAG_DUMP| + TAG_GREEN| + TAG_RED| + TAG_ERR + ); printf("hello solo\r\n"); // Test flash @@ -50,6 +184,24 @@ int main(void) memmove(buf,(uint8_t*)flash_addr(60),sizeof(str)); printf("flash: \"%s\"\r\n", buf); + // test_atomic_counter(); + + + // Note that 4 byte aligned addresses won't get written correctly. + flash_erase_page(60); + uint32_t count = 0; + flash_write(flash_addr(60) + 0,(uint8_t*)&count,4); + count += 1; + flash_write(flash_addr(60) + 4,(uint8_t*)&count,4); + count += 1; + flash_write(flash_addr(60) + 8,(uint8_t*)&count,4); + count += 1; + flash_write(flash_addr(60) + 12,(uint8_t*)&count,4); + count += 1; + flash_write(flash_addr(60) + 16,(uint8_t*)&count,4); + dump_hex((uint8_t *)flash_addr(60), 20); + + // test timer uint32_t t1 = millis(); delay(100); @@ -63,7 +215,7 @@ int main(void) /*// Test PWM + weighting of RGB*/ /*led_test_colors();*/ - + fifo_test(); uint32_t t0 = millis(); @@ -91,15 +243,9 @@ int main(void) fifo_hidmsg_take(hidbuf); dump_hex(hidbuf, HID_PACKET_SIZE); } + while(1) + ; } } - -void _Error_Handler(char *file, int line) -{ - printf("Error: %s: %d\r\n", file, line); - while(1) - { - } -} #endif diff --git a/targets/stm32l442/stm32l432xx.ld b/targets/stm32l442/stm32l432xx.ld index 762abfe..2c44fe9 100644 --- a/targets/stm32l442/stm32l432xx.ld +++ b/targets/stm32l442/stm32l432xx.ld @@ -41,7 +41,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ /* Specify the memory areas */ MEMORY { -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 240K /* Leave out 16 Kb for data */ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 238K /* Leave out 18 Kb for data */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K SRAM2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K } diff --git a/tools/ctap_test.py b/tools/ctap_test.py index c80b36d..0dc807e 100644 --- a/tools/ctap_test.py +++ b/tools/ctap_test.py @@ -387,13 +387,13 @@ class Tester(): def test_u2f(self,): pass - def test_fido2_simple(self): + def test_fido2_simple(self, pin_token=None): creds = [] exclude_list = [] rp = {'id': 'examplo.org', 'name': 'ExaRP'} user = {'id': b'usee_od', 'name': 'AB User'} challenge = 'Y2hhbGxlbmdl' - PIN = None + PIN = pin_token fake_id1 = array.array('B',[randint(0,255) for i in range(0,150)]).tostring() fake_id2 = array.array('B',[randint(0,255) for i in range(0,73)]).tostring() @@ -488,6 +488,7 @@ class Tester(): attest.verify(data.hash) cred = attest.auth_data.credential_data creds.append(cred) + print(cred) print('PASS') if PIN is not None: @@ -511,15 +512,19 @@ class Tester(): real_excl = [{'id': cred.credential_id, 'type': 'public-key'}] try: attest, data = self.client.make_credential(rp, user, challenge, pin = PIN, exclude_list = exclude_list + real_excl) + raise RuntimeError('Exclude list did not return expected error') except CtapError as e: assert(e.code == CtapError.ERR.CREDENTIAL_EXCLUDED) + except ClientError as e: + assert(e.cause.code == CtapError.ERR.CREDENTIAL_EXCLUDED) print('PASS') - print('get assertion') - allow_list = [{'id':creds[0].credential_id, 'type': 'public-key'}] - assertions, client_data = self.client.get_assertion(rp['id'], challenge, allow_list, pin = PIN) - assertions[0].verify(client_data.hash, creds[0].public_key) - print('PASS') + for i, x in enumerate(creds): + print('get assertion %d' % i) + allow_list = [{'id':x.credential_id, 'type': 'public-key'}] + assertions, client_data = self.client.get_assertion(rp['id'], challenge, allow_list, pin = PIN) + assertions[0].verify(client_data.hash, x.public_key) + print('PASS') if PIN is not None: print('get assertion with wrong pin code') @@ -531,11 +536,16 @@ class Tester(): assert(e.cause.code == CtapError.ERR.PIN_INVALID) print('PASS') + print('get multiple assertions') allow_list = [{'id': x.credential_id, 'type': 'public-key'} for x in creds] assertions, client_data = self.client.get_assertion(rp['id'], challenge, allow_list, pin = PIN) + for ass,cred in zip(assertions, creds): + i += 1 + ass.verify(client_data.hash, cred.public_key) + print('%d verified' % i) print('PASS') print('Reset device') @@ -573,6 +583,20 @@ class Tester(): assert(e.code == CtapError.ERR.PIN_INVALID) print('PASS') + print('MC using wrong pin') + try: + self.test_fido2_simple('abcd3'); + except CtapError as e: + assert(e.code == CtapError.ERR.PIN_INVALID) + except ClientError as e: + assert(e.cause.code == CtapError.ERR.PIN_INVALID) + print('PASS') + + print('Reboot device and hit enter') + input() + self.find_device() + self.test_fido2_simple(PIN); + print('Re-run make_credential and get_assertion tests with pin code') test(self, PIN) @@ -583,7 +607,6 @@ class Tester(): print('Warning, reset failed: ', e) print('PASS') - def test_find_brute_force(): i = 0 while 1: @@ -602,6 +625,6 @@ if __name__ == '__main__': # t.test_hid() # t.test_long_ping() t.test_fido2() - #test_find_brute_force() + # test_find_brute_force() #t.test_fido2_simple() #t.test_fido2_brute_force() diff --git a/tools/gencert/cbytes.py b/tools/gencert/cbytes.py index 6ad5fa5..b37c5bd 100644 --- a/tools/gencert/cbytes.py +++ b/tools/gencert/cbytes.py @@ -1,5 +1,6 @@ #!/usr/bin/env python from __future__ import print_function +import base64 """ cbytes.py @@ -39,4 +40,6 @@ print() print('code uint8_t __attest[] = \n%s;' % c_str) print('const uint16_t __attest_size = sizeof(__attest)-1;') - +b = base64.b64encode(buf) +print('b64: ') +print(b) diff --git a/tools/gencert/gen_intermediate.sh b/tools/gencert/gen_intermediate.sh new file mode 100644 index 0000000..290905f --- /dev/null +++ b/tools/gencert/gen_intermediate.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +keyname=interkey.pem +certname=intercert.pem +smallcertname=intercert.der +curve=prime256v1 + +[[ "$#" != 2 ]] && echo "usage: $0 " && exit 1 + +# generate EC private key +openssl ecparam -genkey -name "$curve" -out "$keyname" -rand seed.txt + +# generate a "signing request" +openssl req -new -key "$keyname" -out "$keyname".csr -subj "/C=US/ST=Maryland/O=Solo Keys/OU=Authenticator Attestation/CN=solokeys.com/emailAddress=hello@solokeys.com" + +# sign the request +openssl x509 -req -days 18250 -in "$keyname".csr -extfile v3.ext -CA "$2" -CAkey "$1" -set_serial 01 -out "$certname" -sha256 + +# convert to smaller size format DER +openssl x509 -in $certname -outform der -out $smallcertname + +openssl x509 -in $certname -text -noout diff --git a/tools/gencert/genca.sh b/tools/gencert/genca.sh index 3ee8b62..f282fdf 100644 --- a/tools/gencert/genca.sh +++ b/tools/gencert/genca.sh @@ -6,12 +6,13 @@ smallcertname=cert.der curve=prime256v1 # generate EC private key -openssl ecparam -genkey -name "$curve" -out "$keyname" +openssl ecparam -genkey -name "$curve" -out "$keyname" -rand seed.txt # generate a "signing request" -openssl req -new -key "$keyname" -out "$keyname".csr +openssl req -new -key "$keyname" -out "$keyname".csr -subj "/C=US/ST=Maryland/O=Solo Keys/OU=Root CA/CN=solokeys.com/emailAddress=hello@solokeys.com" # self sign the request -openssl x509 -req -days 18250 -in "$keyname".csr -signkey "$keyname" -out "$certname" +openssl x509 -trustout -req -days 18250 -in "$keyname".csr -signkey "$keyname" -out "$certname" -sha256 # convert to smaller size format DER openssl x509 -in $certname -outform der -out $smallcertname +openssl x509 -in $certname -text -noout diff --git a/tools/gencert/print_x_y.py b/tools/gencert/print_x_y.py new file mode 100644 index 0000000..9c61d96 --- /dev/null +++ b/tools/gencert/print_x_y.py @@ -0,0 +1,16 @@ +import sys +from ecdsa import SigningKey, NIST256p + +sk = SigningKey.from_pem(open(sys.argv[1]).read()) + + +print('Private key in various formats:') +print() +print([c for c in sk.to_string()]) +print() +print(''.join(['%02x'%c for c in sk.to_string()])) +print() +print('"\\x' + '\\x'.join(['%02x'%c for c in sk.to_string()]) + '"') +print() + + diff --git a/tools/gencert/verify_certs.sh b/tools/gencert/verify_certs.sh new file mode 100644 index 0000000..520678e --- /dev/null +++ b/tools/gencert/verify_certs.sh @@ -0,0 +1,22 @@ + +# verify that the root CA/keypair and intermediate CA/keypairs are set up correctly. + +[[ "$#" != 4 ]] && echo "usage: $0 " && exit 1 + +ikey=$1 +icert=$2 + +rkey=$3 +rcert=$4 + +echo 'challenge $RANDOM' > chal.txt + +# check that they are actual key pairs +openssl dgst -sha256 -sign "$ikey" -out sig.txt chal.txt +openssl dgst -sha256 -verify <(openssl x509 -in "$icert" -pubkey -noout) -signature sig.txt chal.txt + +openssl dgst -sha256 -sign "$rkey" -out sig.txt chal.txt +openssl dgst -sha256 -verify <(openssl x509 -in "$rcert" -pubkey -noout) -signature sig.txt chal.txt + +# Check they are a chain +openssl verify -verbose -CAfile "$rcert" "$icert" From 707a930d3384b62b9ee446f76040963548db7cb2 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 28 Oct 2018 16:39:38 -0400 Subject: [PATCH 18/26] development attestation key pair --- targets/stm32l442/Makefile | 2 +- targets/stm32l442/src/attestation.c | 39 +++++++++++++++++++++++++++++ targets/stm32l442/src/crypto.c | 34 ------------------------- 3 files changed, 40 insertions(+), 35 deletions(-) create mode 100644 targets/stm32l442/src/attestation.c diff --git a/targets/stm32l442/Makefile b/targets/stm32l442/Makefile index 55802c1..7dd2ea3 100644 --- a/targets/stm32l442/Makefile +++ b/targets/stm32l442/Makefile @@ -5,7 +5,7 @@ AR=arm-none-eabi-ar # 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/fifo.c src/crypto.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) diff --git a/targets/stm32l442/src/attestation.c b/targets/stm32l442/src/attestation.c new file mode 100644 index 0000000..d80579d --- /dev/null +++ b/targets/stm32l442/src/attestation.c @@ -0,0 +1,39 @@ +#include +#include "crypto.h" + +// For testing/development only + +const uint8_t attestation_cert_der[] = +"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08" +"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" +"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e" +"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38" +"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32" +"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" +"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x0f\x30\x0d" +"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55" +"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20" +"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72" +"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04" +"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07" +"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00" +"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf" +"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83" +"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca" +"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d" +"\xa1\x30\xa4\x2e\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31" +"\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e\x06\x03\x55\x04" +"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94" +"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04" +"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00" +"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e" +"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd" +"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7" +"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7"; + + +const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1; + + +const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30"; +const uint16_t attestation_key_size = sizeof(attestation_key)-1; diff --git a/targets/stm32l442/src/crypto.c b/targets/stm32l442/src/crypto.c index 6d7a351..c22067b 100644 --- a/targets/stm32l442/src/crypto.c +++ b/targets/stm32l442/src/crypto.c @@ -321,40 +321,6 @@ void crypto_aes256_encrypt(uint8_t * buf, int length) } -const uint8_t attestation_cert_der[] = -"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08" -"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" -"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e" -"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38" -"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32" -"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" -"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x0f\x30\x0d" -"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55" -"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20" -"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72" -"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04" -"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07" -"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00" -"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf" -"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83" -"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca" -"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d" -"\xa1\x30\xa4\x2e\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31" -"\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e\x06\x03\x55\x04" -"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94" -"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04" -"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00" -"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e" -"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd" -"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7" -"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7"; - - -const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1; - - -const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30"; -const uint16_t attestation_key_size = sizeof(attestation_key)-1; #else From 5993aa792a766902bb9cd003c3dd1974ae83f36d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 28 Oct 2018 20:09:12 -0400 Subject: [PATCH 19/26] fix compile warnings, add flash locking --- fido2/crypto.h | 7 +++-- fido2/ctap.c | 4 +-- fido2/device.h | 2 ++ fido2/main.c | 18 +++--------- fido2/test_power.c | 2 +- targets/stm32l442/Makefile | 11 ++++--- targets/stm32l442/src/app.h | 10 ++----- targets/stm32l442/src/crypto.c | 30 +++++++++---------- targets/stm32l442/src/device.c | 16 +++++------ targets/stm32l442/src/fifo.c | 2 +- targets/stm32l442/src/flash.c | 49 +++++++++++++++++++++++++++++++- targets/stm32l442/src/flash.h | 1 + targets/stm32l442/src/led.c | 19 ++++++------- targets/stm32l442/src/redirect.c | 5 +++- 14 files changed, 107 insertions(+), 69 deletions(-) diff --git a/fido2/crypto.h b/fido2/crypto.h index 497ebf5..685908e 100644 --- a/fido2/crypto.h +++ b/fido2/crypto.h @@ -49,8 +49,8 @@ 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_KEY NULL -#define CRYPTO_MASTER_KEY NULL +#define CRYPTO_TRANSPORT_KEY ((uint8_t*)1) +#define CRYPTO_MASTER_KEY ((uint8_t*)0) void crypto_aes256_init(uint8_t * key, uint8_t * nonce); void crypto_aes256_reset_iv(uint8_t * nonce); @@ -66,6 +66,7 @@ void crypto_load_master_secret(uint8_t * key); extern const uint8_t attestation_cert_der[]; extern const uint16_t attestation_cert_der_size; - +extern const uint8_t attestation_key[]; +extern const uint16_t attestation_key_size; #endif diff --git a/fido2/ctap.c b/fido2/ctap.c index c3b4a4c..ba641e5 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -269,12 +269,12 @@ static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input, void make_auth_tag(uint8_t * nonce, CTAP_userEntity * user, uint32_t count, uint8_t * tag) { uint8_t hashbuf[32]; - crypto_sha256_hmac_init(NULL, 0, hashbuf); + crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY, 0, hashbuf); crypto_sha256_update(nonce, CREDENTIAL_NONCE_SIZE); crypto_sha256_update(user->id, user->id_size); crypto_sha256_update(user->name, strnlen((const char*)user->name, USER_NAME_LIMIT)); crypto_sha256_update((uint8_t*)&count, 4); - crypto_sha256_hmac_final(NULL,0,hashbuf); + crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY,0,hashbuf); memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE); } diff --git a/fido2/device.h b/fido2/device.h index adbc842..e750568 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -28,6 +28,8 @@ void device_init(); uint32_t millis(); +void delay(uint32_t ms); + // HID message size in bytes #define HID_MESSAGE_SIZE 64 diff --git a/fido2/main.c b/fido2/main.c index 797c856..8c2cdb3 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -36,12 +36,8 @@ int main(int argc, char * argv[]) { - int count = 0; - uint32_t t1 = 0; - uint32_t t2 = 0; - uint32_t accum = 0; - uint32_t dt = 0; uint8_t hidmsg[64]; + uint32_t t1 = 0; set_logging_mask( /*0*/ @@ -51,11 +47,11 @@ int main(int argc, char * argv[]) // TAG_WALLET | TAG_STOR | // TAG_CP | - TAG_CTAP| + // TAG_CTAP| // TAG_HID| /*TAG_U2F|*/ // TAG_PARSE | - //TAG_TIME| + // TAG_TIME| // TAG_DUMP| TAG_GREEN| TAG_RED| @@ -89,24 +85,18 @@ int main(int argc, char * argv[]) if (usbhid_recv(hidmsg) > 0) { - t2 = millis(); ctaphid_handle_packet(hidmsg); - accum += millis() - t2; - // printf1(TAG_TIME,"accum: %d\n", (uint32_t)accum); - // printf1(TAG_TIME,"dt: %d\n", t2 - dt); - dt = t2; memset(hidmsg, 0, sizeof(hidmsg)); } else { - /*main_loop_delay();*/ } ctaphid_check_timeouts(); } // Should never get here usbhid_close(); - printf("done\n"); + printf1(TAG_GREEN, "done\n"); return 0; } diff --git a/fido2/test_power.c b/fido2/test_power.c index 607e732..38e2b4f 100644 --- a/fido2/test_power.c +++ b/fido2/test_power.c @@ -124,7 +124,7 @@ int main(int argc, char * argv[]) // Should never get here usbhid_close(); - printf("done\n"); + printf1(TAG_GREEN, "done\n"); return 0; } diff --git a/targets/stm32l442/Makefile b/targets/stm32l442/Makefile index 7dd2ea3..e8f209c 100644 --- a/targets/stm32l442/Makefile +++ b/targets/stm32l442/Makefile @@ -42,7 +42,7 @@ CHIP=STM32L442xx DEFINES = -D$(CHIP) -DAES256=1 -DUSE_FULL_LL_DRIVER # DEFINES += -DTEST_SOLO_STM32 -DTEST -DTEST_FIFO=1 -CFLAGS=$(INC) -c $(DEFINES) -Os -Wall -fdata-sections -ffunction-sections $(HW) +CFLAGS=$(INC) -c $(DEFINES) -Wall -fdata-sections -ffunction-sections $(HW) 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 -ltinycbor @@ -53,11 +53,13 @@ all: $(TARGET).elf $(SZ) $^ %.o: %.c - $(CC) $^ $(HW) $(CFLAGS) -o $@ + $(CC) $^ $(HW) -Os $(CFLAGS) -o $@ +../../crypto/micro-ecc/uECC.o: ../../crypto/micro-ecc/uECC.c + $(CC) $^ $(HW) -O3 $(CFLAGS) -o $@ %.o: %.s - $(CC) $^ $(HW) $(CFLAGS) -o $@ + $(CC) $^ $(HW) -Os $(CFLAGS) -o $@ %.elf: $(OBJ) $(CC) $^ $(HW) $(LDFLAGS) -o $@ @@ -69,8 +71,9 @@ clean: rm -f *.o src/*.o src/*.elf *.elf *.hex $(OBJ) flash: $(TARGET).hex - STM32_Programmer_CLI -c port=SWD -halt -e all + STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect STM32_Programmer_CLI -c port=SWD -halt -d $(TARGET).hex -rst + STM32_Programmer_CLI -c port=SWD -rst sleep 0.5 python dfuse-tool/dfuse-tool.py --leave diff --git a/targets/stm32l442/src/app.h b/targets/stm32l442/src/app.h index 0db87d3..6a31791 100644 --- a/targets/stm32l442/src/app.h +++ b/targets/stm32l442/src/app.h @@ -4,15 +4,10 @@ #define DEBUG_UART USART1 - - - -#define DEBUG_LEVEL 1 +#define DEBUG_LEVEL 1 #define NON_BLOCK_PRINTING 0 -//#define PRINTING_USE_VCOM - //#define USING_DEV_BOARD //#define ENABLE_U2F_EXTENSIONS @@ -35,6 +30,7 @@ void hw_init(void); #define SOLO_BUTTON_PORT GPIOA #define SOLO_BUTTON_PIN LL_GPIO_PIN_0 -#define SKIP_BUTTON_CHECK 1 +#define SKIP_BUTTON_CHECK_WITH_DELAY 1 +#define SKIP_BUTTON_CHECK_FAST 0 #endif diff --git a/targets/stm32l442/src/crypto.c b/targets/stm32l442/src/crypto.c index c22067b..70cd626 100644 --- a/targets/stm32l442/src/crypto.c +++ b/targets/stm32l442/src/crypto.c @@ -19,6 +19,7 @@ #include "ctap.h" #include "device.h" #include "app.h" +#include "log.h" typedef enum @@ -39,14 +40,6 @@ typedef enum } mbedtls_ecp_group_id; - -const uint8_t attestation_cert_der[]; -const uint16_t attestation_cert_der_size; -const uint8_t attestation_key[]; -const uint16_t attestation_key_size; - - - static SHA256_CTX sha256_ctx; static const struct uECC_Curve_t * _es256_curve = NULL; static const uint8_t * _signing_key = NULL; @@ -105,10 +98,15 @@ void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac) key = master_secret; klen = sizeof(master_secret)/2; } + else if (key == CRYPTO_TRANSPORT_KEY) + { + key = transport_secret; + klen = 32; + } if(klen > 64) { - printf("Error, key size must be <= 64\n"); + printf2(TAG_ERR, "Error, key size must be <= 64\n"); exit(1); } @@ -138,7 +136,7 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac) if(klen > 64) { - printf("Error, key size must be <= 64\n"); + printf2(TAG_ERR, "Error, key size must be <= 64\n"); exit(1); } memmove(buf, key, klen); @@ -172,7 +170,7 @@ void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig) { if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0) { - printf("error, uECC failed\n"); + printf2(TAG_ERR, "error, uECC failed\n"); exit(1); } } @@ -209,19 +207,19 @@ void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_I if (_key_len != 32) goto fail; break; default: - printf("error, invalid ECDSA alg specifier\n"); + printf2(TAG_ERR, "error, invalid ECDSA alg specifier\n"); exit(1); } if ( uECC_sign(_signing_key, data, len, sig, curve) == 0) { - printf("error, uECC failed\n"); + printf2(TAG_ERR, "error, uECC failed\n"); exit(1); } return; fail: - printf("error, invalid key length\n"); + printf2(TAG_ERR, "error, invalid key length\n"); exit(1); } @@ -261,7 +259,7 @@ void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey) { if (uECC_make_key(pubkey, privkey, _es256_curve) != 1) { - printf("Error, uECC_make_key failed\n"); + printf2(TAG_ERR, "Error, uECC_make_key failed\n"); exit(1); } } @@ -270,7 +268,7 @@ void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey { if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1) { - printf("Error, uECC_shared_secret failed\n"); + printf2(TAG_ERR, "Error, uECC_shared_secret failed\n"); exit(1); } diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index f4ecb7f..2033b47 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -95,6 +95,7 @@ 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); + flash_option_bytes_init(0); printf1(TAG_GEN,"hello solo\r\n"); } @@ -337,9 +338,8 @@ static int handle_packets() int ctap_user_presence_test() { - int oldstatus = __device_status; int ret; -#if SKIP_BUTTON_CHECK +#if SKIP_BUTTON_CHECK_WITH_DELAY int i=500; while(i--) { @@ -348,17 +348,15 @@ int ctap_user_presence_test() if (ret) return ret; } goto done; +#elif SKIP_BUTTON_CHECK_FAST + delay(2); + ret = handle_packets(); + if (ret) return ret; + goto done; #endif - uint32_t t1 = millis(); led_rgb(0xff3520); -#if USE_BUTTON_DELAY - delay(3000); - led_rgb(0x001040); - delay(50); - goto done; -#endif while (IS_BUTTON_PRESSED()) { if (t1 + 5000 < millis()) diff --git a/targets/stm32l442/src/fifo.c b/targets/stm32l442/src/fifo.c index cd13348..645c28b 100644 --- a/targets/stm32l442/src/fifo.c +++ b/targets/stm32l442/src/fifo.c @@ -4,7 +4,7 @@ #include "fifo.h" -FIFO_CREATE(debug,1024,1) +FIFO_CREATE(debug,4096,1) FIFO_CREATE(hidmsg,100,64) diff --git a/targets/stm32l442/src/flash.c b/targets/stm32l442/src/flash.c index d87a002..1b09d66 100644 --- a/targets/stm32l442/src/flash.c +++ b/targets/stm32l442/src/flash.c @@ -6,6 +6,7 @@ #include "app.h" #include "flash.h" #include "log.h" +#include "device.h" static void flash_unlock() { @@ -15,13 +16,57 @@ static void flash_unlock() FLASH->KEYR = 0xCDEF89AB; } } + +// Locks flash and turns off DFU +void flash_option_bytes_init(int boot_from_dfu) +{ +#if DEBUG_LEVEL + uint32_t val = 0xfffff8aa; +#else + uint32_t val = 0xfffff8b9; +#endif + if (!boot_from_dfu) + { + val &= ~(1<<26); // nSWBOOT0 = 0 (boot from nBoot0) + } + val &= ~(1<<25); // SRAM2_RST = 1 (erase sram on reset) + val &= ~(1<<24); // SRAM2_PE = 1 (parity check en) + + if (FLASH->OPTR == val) + { + return; + } + + __disable_irq(); + while (FLASH->SR & (1<<16)) + ; + flash_unlock(); + if (FLASH->CR & (1<<30)) + { + FLASH->OPTKEYR = 0x08192A3B; + FLASH->OPTKEYR = 0x4C5D6E7F; + } + + FLASH->OPTR =val; + FLASH->CR |= (1<<17); + + while (FLASH->SR & (1<<16)) + ; + + flash_lock(); + + __enable_irq(); +} + void flash_erase_page(uint8_t page) { __disable_irq(); - flash_unlock(); + // Wait if flash is busy while (FLASH->SR & (1<<16)) ; + flash_unlock(); + FLASH->SR = FLASH->SR; // enable flash erase and select page @@ -72,6 +117,8 @@ void flash_write(uint32_t addr, uint8_t * data, size_t sz) { int i; uint8_t buf[8]; + while (FLASH->SR & (1<<16)) + ; flash_unlock(); // dword align diff --git a/targets/stm32l442/src/flash.h b/targets/stm32l442/src/flash.h index e4841df..f099700 100644 --- a/targets/stm32l442/src/flash.h +++ b/targets/stm32l442/src/flash.h @@ -4,6 +4,7 @@ void flash_erase_page(uint8_t page); void flash_write_dword(uint32_t addr, uint64_t data); void flash_write(uint32_t addr, uint8_t * data, size_t sz); +void flash_option_bytes_init(int boot_from_dfu); #define FLASH_PAGE_SIZE 2048 diff --git a/targets/stm32l442/src/led.c b/targets/stm32l442/src/led.c index f8373aa..2393d7b 100644 --- a/targets/stm32l442/src/led.c +++ b/targets/stm32l442/src/led.c @@ -6,6 +6,7 @@ #include "led.h" #include "device.h" +#include "log.h" void led_rgb(uint32_t hex) { @@ -46,9 +47,9 @@ void led_test_colors() while(1) { - printf("%d: %lu\r\n", j++, millis()); + printf1(TAG_GREEN, "%d: %lu\r\n", j++, millis()); - printf("white pulse\r\n"); + printf1(TAG_GREEN,"white pulse\r\n"); time = millis(); while((millis() - time) < 5000) { @@ -56,7 +57,7 @@ void led_test_colors() led_rgb(i | (i << 8) | (i << 16)); } - printf("blue pulse\r\n"); + printf1(TAG_GREEN,"blue pulse\r\n"); time = millis(); while((millis() - time) < 5000) { @@ -64,7 +65,7 @@ void led_test_colors() led_rgb(i); } - printf("green pulse\r\n"); + printf1(TAG_GREEN,"green pulse\r\n"); time = millis(); while((millis() - time) < 5000) { @@ -72,7 +73,7 @@ void led_test_colors() led_rgb(i<<8); } - printf("red pulse\r\n"); + printf1(TAG_GREEN,"red pulse\r\n"); time = millis(); while((millis() - time) < 5000) { @@ -80,7 +81,7 @@ void led_test_colors() led_rgb(i<<16); } - printf("purple pulse\r\n"); + printf1(TAG_GREEN,"purple pulse\r\n"); time = millis(); while((millis() - time) < 5000) { @@ -88,7 +89,7 @@ void led_test_colors() led_rgb((i<<16) | i); } - printf("orange pulse\r\n"); + printf1(TAG_GREEN,"orange pulse\r\n"); time = millis(); while((millis() - time) < 5000) { @@ -96,7 +97,7 @@ void led_test_colors() led_rgb((i<<16) | (i<<8)); } - printf("yellow pulse\r\n"); + printf1(TAG_GREEN,"yellow pulse\r\n"); time = millis(); while((millis() - time) < 5000) { @@ -105,5 +106,3 @@ void led_test_colors() } } } - - diff --git a/targets/stm32l442/src/redirect.c b/targets/stm32l442/src/redirect.c index 0f997d6..5c8dbf4 100644 --- a/targets/stm32l442/src/redirect.c +++ b/targets/stm32l442/src/redirect.c @@ -3,7 +3,7 @@ #include "app.h" #include "fifo.h" - +#if DEBUG_LEVEL>0 void _putchar(char c) { @@ -16,6 +16,8 @@ void _putchar(char c) #endif } + + int _write (int fd, const void *buf, long int len) { uint8_t * data = (uint8_t *) buf; @@ -26,3 +28,4 @@ int _write (int fd, const void *buf, long int len) return 0; } +#endif From 32f0d2675e54ec42dfc0c97a7a5e5e8eacbc5883 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 28 Oct 2018 20:39:56 -0400 Subject: [PATCH 20/26] entering and leaving dfu --- targets/stm32l442/Makefile | 6 +++--- targets/stm32l442/src/flash.c | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/targets/stm32l442/Makefile b/targets/stm32l442/Makefile index e8f209c..54209d2 100644 --- a/targets/stm32l442/Makefile +++ b/targets/stm32l442/Makefile @@ -73,9 +73,9 @@ clean: flash: $(TARGET).hex STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect STM32_Programmer_CLI -c port=SWD -halt -d $(TARGET).hex -rst - STM32_Programmer_CLI -c port=SWD -rst - sleep 0.5 - python dfuse-tool/dfuse-tool.py --leave + +detach: + STM32_Programmer_CLI -c port=usb1 -ob nBOOT0=1 cbor: cd ../../tinycbor/ && make clean diff --git a/targets/stm32l442/src/flash.c b/targets/stm32l442/src/flash.c index 1b09d66..fafe136 100644 --- a/targets/stm32l442/src/flash.c +++ b/targets/stm32l442/src/flash.c @@ -25,10 +25,12 @@ void flash_option_bytes_init(int boot_from_dfu) #else uint32_t val = 0xfffff8b9; #endif - if (!boot_from_dfu) + + if (boot_from_dfu) { - val &= ~(1<<26); // nSWBOOT0 = 0 (boot from nBoot0) + val &= ~(1<<27); // nBOOT0 = 0 (boot from system rom) } + val &= ~(1<<26); // nSWBOOT0 = 0 (boot from nBoot0) val &= ~(1<<25); // SRAM2_RST = 1 (erase sram on reset) val &= ~(1<<24); // SRAM2_PE = 1 (parity check en) From ba82400b6ca48de7a5778476c7169835ff6107a2 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 28 Oct 2018 20:50:20 -0400 Subject: [PATCH 21/26] reset transport key --- targets/stm32l442/src/crypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/targets/stm32l442/src/crypto.c b/targets/stm32l442/src/crypto.c index 70cd626..834040a 100644 --- a/targets/stm32l442/src/crypto.c +++ b/targets/stm32l442/src/crypto.c @@ -68,7 +68,9 @@ void crypto_load_master_secret(uint8_t * key) void crypto_reset_master_secret() { memset(master_secret, 0, 64); + memset(transport_secret, 0, 64); ctap_generate_rng(master_secret, 64); + ctap_generate_rng(transport_secret, 32); } From 898a7a303c85dde1c725abc92f5ce8764de17b5a Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 28 Oct 2018 22:14:36 -0400 Subject: [PATCH 22/26] add aes in keygen --- fido2/ctap.c | 5 ++--- targets/stm32l442/src/crypto.c | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fido2/ctap.c b/fido2/ctap.c index ba641e5..d5deb3e 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -354,7 +354,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au ctap_generate_rng(authData->attest.credential.nonce, CREDENTIAL_NONCE_SIZE); - memmove(&authData->attest.credential.enc.user, user, sizeof(CTAP_userEntity)); //TODO encrypt this + memmove(&authData->attest.credential.enc.user, user, sizeof(CTAP_userEntity)); authData->attest.credential.enc.count = count; // Make a tag we can later check to make sure this is a token we made @@ -1550,7 +1550,6 @@ int8_t ctap_store_key(uint8_t index, uint8_t * key, uint16_t len) memmove(STATE.key_space + offset, key, len); - ctap_flush_state(0); ctap_flush_state(1); return 0; @@ -1602,5 +1601,5 @@ void ctap_reset() memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH)); crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); - crypto_reset_master_secret(); // Not sure what the significance of this is?? + crypto_reset_master_secret(); } diff --git a/targets/stm32l442/src/crypto.c b/targets/stm32l442/src/crypto.c index 834040a..c2562a7 100644 --- a/targets/stm32l442/src/crypto.c +++ b/targets/stm32l442/src/crypto.c @@ -233,6 +233,9 @@ void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, ui crypto_sha256_update(data2, len2); crypto_sha256_update(master_secret, 32); // TODO AES crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey); + + crypto_aes256_init(master_secret + 32, NULL); + crypto_aes256_encrypt(privkey, 32); } From 80842dab296618a860544f7e7dae032cc20b598e Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 30 Oct 2018 01:50:46 -0400 Subject: [PATCH 23/26] passing u2f usbhid test --- fido2/ctaphid.c | 40 +++++++++++++++++++++------ targets/stm32l442/lib/usbd/usbd_hid.h | 2 +- targets/stm32l442/src/crypto.c | 2 +- targets/stm32l442/src/device.c | 4 +-- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 46d5523..e67cbb0 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -223,7 +223,6 @@ static int buffer_packet(CTAPHID_PACKET * pkt) static void buffer_reset() { - ctap_buffer_bcnt = 0; ctap_buffer_offset = 0; ctap_packet_seq = 0; @@ -363,7 +362,12 @@ void ctaphid_check_timeouts() { printf1(TAG_HID, "TIMEOUT CID: %08x\n", CIDS[i].cid); ctaphid_send_error(CIDS[i].cid, CTAP1_ERR_TIMEOUT); - memset(CIDS + i, 0, sizeof(struct CID)); + CIDS[i].busy = 0; + if (CIDS[i].cid == buffer_cid()) + { + buffer_reset(); + } + // memset(CIDS + i, 0, sizeof(struct CID)); } } @@ -447,12 +451,20 @@ static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * ci } else { - // Check if matches existing CID if (pkt->cid == CTAPHID_BROADCAST_CID) { *cmd = CTAP1_ERR_INVALID_CHANNEL; return HID_ERROR; } + + if (! cid_exists(pkt->cid) && ! is_cont_pkt(pkt)) + { + if (buffer_status() == EMPTY) + { + add_cid(pkt->cid); + } + } + if (cid_exists(pkt->cid)) { if (buffer_status() == BUFFERING) @@ -466,9 +478,17 @@ static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * ci } else if (pkt->cid != buffer_cid()) { - printf2(TAG_ERR,"BUSY with %08x\n", buffer_cid()); - *cmd = CTAP1_ERR_CHANNEL_BUSY; - return HID_ERROR; + if (! is_cont_pkt(pkt)) + { + printf2(TAG_ERR,"BUSY with %08x\n", buffer_cid()); + *cmd = CTAP1_ERR_CHANNEL_BUSY; + return HID_ERROR; + } + else + { + printf2(TAG_ERR,"ignoring random cont packet from %04x\n",pkt->cid); + return HID_IGNORE; + } } } if (! is_cont_pkt(pkt)) @@ -484,10 +504,11 @@ static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * ci { if (buffer_status() == EMPTY || pkt->cid != buffer_cid()) { - printf2(TAG_ERR,"ignoring random cont packet\n"); + printf2(TAG_ERR,"ignoring random cont packet from %04x\n",pkt->cid); return HID_IGNORE; } } + if (buffer_packet(pkt) == SEQUENCE_ERROR) { printf2(TAG_ERR,"Buffering sequence error\n"); @@ -544,7 +565,10 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) if (bufstatus == HID_ERROR) { cid_del(cid); - buffer_reset(); + if (cmd == CTAP1_ERR_INVALID_SEQ) + { + buffer_reset(); + } ctaphid_send_error(cid, cmd); return 0; } diff --git a/targets/stm32l442/lib/usbd/usbd_hid.h b/targets/stm32l442/lib/usbd/usbd_hid.h index 4d61cb6..03dcb89 100644 --- a/targets/stm32l442/lib/usbd/usbd_hid.h +++ b/targets/stm32l442/lib/usbd/usbd_hid.h @@ -66,7 +66,7 @@ #define HID_DESCRIPTOR_TYPE 0x21U #define HID_REPORT_DESC 0x22U -#define HID_BINTERVAL 10 +#define HID_BINTERVAL 5 #define HID_REQ_SET_PROTOCOL 0x0BU #define HID_REQ_GET_PROTOCOL 0x03U diff --git a/targets/stm32l442/src/crypto.c b/targets/stm32l442/src/crypto.c index c2562a7..be437b8 100644 --- a/targets/stm32l442/src/crypto.c +++ b/targets/stm32l442/src/crypto.c @@ -68,7 +68,7 @@ void crypto_load_master_secret(uint8_t * key) void crypto_reset_master_secret() { memset(master_secret, 0, 64); - memset(transport_secret, 0, 64); + memset(transport_secret, 0, 32); ctap_generate_rng(master_secret, 64); ctap_generate_rng(transport_secret, 32); } diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 2033b47..3f118ac 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -48,7 +48,7 @@ void TIM6_DAC_IRQHandler() // timer is only 16 bits, so roll it over here TIM6->SR = 0; __90_ms += 1; - if ((millis() - __last_update) > 5) + if ((millis() - __last_update) > 8) { if (__device_status != CTAPHID_STATUS_IDLE) { @@ -376,8 +376,6 @@ do { goto fail; } - if (! IS_BUTTON_PRESSED()) - continue; delay(1); ret = handle_packets(); if (ret) return ret; From f512fd883193878ec0bee4e89ac4c3e9797cec6d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 2 Nov 2018 00:10:22 -0400 Subject: [PATCH 24/26] too unclear what is happening --- Makefile | 15 +++++++-------- docs/documenting.md | 6 +++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index a9e0191..2980f0b 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ obj = $(src:.c=.o) uECC.o LIBCBOR = tinycbor/lib/libtinycbor.a LDFLAGS = -Wl,--gc-sections $(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 @@ -31,7 +31,7 @@ name = main all: python-fido2 main .PHONY: test -test: +test: $(MAKE) -C . main $(MAKE) -C . testgcm ./testgcm @@ -55,7 +55,7 @@ efm8prog: efm32com: cd './targets/efm32/GNU ARM v7.2.1 - Debug' && $(MAKE) all efm32prog: efm32com - commander flash './targets/efm32/GNU ARM v7.2.1 - Debug/EFM32.hex' $(EFM32_DEBUGGER) -p "0x1E7FC:0x00000000:4" + commander flash './targets/efm32/GNU ARM v7.2.1 - Debug/EFM32.hex' $(EFM32_DEBUGGER) -p "0x1E7FC:0x00000000:4" efm32read: efm32com commander swo read $(EFM32_DEBUGGER) efm32bootprog: efm32com @@ -64,10 +64,10 @@ efm32bootprog: efm32com $(name): $(obj) $(LIBCBOR) $(CC) $(LDFLAGS) -o $@ $(obj) $(LDFLAGS) -crypto/aes-gcm/aes_gcm.o: +crypto/aes-gcm/aes_gcm.o: $(CC) -c crypto/aes-gcm/aes_gcm.c $(CFLAGS) -DTEST -o crypto/aes-gcm/aes_gcm.o -testgcm: $(obj) $(LIBCBOR) crypto/aes-gcm/aes_gcm.o +testgcm: $(obj) $(LIBCBOR) crypto/aes-gcm/aes_gcm.o $(CC) -c fido2/main.c $(CFLAGS) -DTEST -o fido2/main.o $(CC) $(LDFLAGS) -o $@ $^ $(LDFLAGS) @@ -86,11 +86,11 @@ venv: echo " pip install virtualenv" ;\ fi virtualenv venv - ./venv/bin/pip install wheel + ./venv/bin/pip install wheel .PHONY: python-fido2 python-fido2: venv - cd python-fido2/ && ../venv/bin/python setup.py install + cd python-fido2/ && ../venv/bin/python setup.py install venv/bin/mkdocs: venv ./venv/bin/pip install mkdocs mkdocs-material @@ -111,4 +111,3 @@ clean: fi ;\ done rm -rf venv - diff --git a/docs/documenting.md b/docs/documenting.md index 012d8d1..f55a718 100644 --- a/docs/documenting.md +++ b/docs/documenting.md @@ -2,6 +2,10 @@ Documentation of the `master` branch is deployed to Netlify automatically. To host or develop locally: -- `make docsrv` and visit [localhost:8000](http://localhost:8000). +``` +pip install mkdocs mkdocs-material +``` + +`make docsrv` and visit [localhost:8000](http://localhost:8000). The file `runtime.txt` is necessary to tell Netlify to use Python3. From e2dec2625deac02ad3beaa3b524fd36b1ecbd9a8 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 2 Nov 2018 00:33:54 -0400 Subject: [PATCH 25/26] document some --- docs/code-overview.md | 40 ++++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 41 insertions(+) create mode 100644 docs/code-overview.md diff --git a/docs/code-overview.md b/docs/code-overview.md new file mode 100644 index 0000000..9852cd9 --- /dev/null +++ b/docs/code-overview.md @@ -0,0 +1,40 @@ +# Overview of firmware + +This is a high level overview of the code. We aim to make the code self documenting +and easy to understand, especially when paired with a high level overview. + +## FIDO2 codebase + +* main.c - calls high level functions and implements event loop. + +* ctaphid.c - implements [USBHID protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#usb) for FIDO. + +* u2f.c - implements [U2F protocol](https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html). + +* ctap.c - implements [CTAP2 protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html). + +* ctap_parse.c - implements parsing for CTAP protocol. + * this could use some work minimizing. + +* log.c - embedded friendly debug logging. + +* crypto.c - software implementation of the crypto needs of the application. Generally this will be copied and edited for different platforms. API defined in crypto.h should be the same. + +* device.h - definitions of functions that are platform specific and should be implemented separately. See device.c in any of the implementations to see examples. + +## Data flow + +The main loop will poll the USB peripheral to see if any messages arrived, +and then pass each one to the USBHID layer. + +Once a USBHID message is fully buffered, it will be acted on, unless there was a previous error. +This will get passed up to U2F or CTAP2 layer. The response is buffered and then written out to USB. + +Depending on platform, there should be a minimum number of interrupts configured. USB will need interrupts, +and possibly timer interrupts for keeping track of time. ST implementation users a 16-bit timer to track time, +and interrupts to count overflows. + +If the application is waiting on user input in CTAP2, then USBHID messages need to be continued to be polled, +to catch any [cancel command](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#usb-hid-cancel). +Also, every 100ms or so, an update needs to be sent via USBHID if the CTAP2 application is still processing a getAssertion request, +a makeCredential request, or is waiting on user input. ST leverages same 16-bit timer interrupt for this. diff --git a/mkdocs.yml b/mkdocs.yml index 92ed99c..508e6ec 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,6 +11,7 @@ nav: - FIDO2 Implementation: fido2-impl.md - Signed update process: signed-updates.md - Building: building.md + - Code documentation: code-overview.md - Contributing Code: contributing.md - Contributing Docs: documenting.md - What the udev?!: udev.md From 29e885d25501d7884d387523112b9d1fb56ea5f8 Mon Sep 17 00:00:00 2001 From: nickray Date: Fri, 2 Nov 2018 16:01:06 +0100 Subject: [PATCH 26/26] git clone needs submodules --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5476d84..1fdcdeb 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ bulk order and provide open source security tokens for everyone that is interest Clone solo and build it ```bash -git clone https://github.com/SoloKeysSec/solo +git clone --recurse-submodules https://github.com/SoloKeysSec/solo cd solo/ make all