Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add keyboard HID interface to Solo #446

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions fido2/ctap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,20 @@ uint8_t ctap_cred_mgmt(CborEncoder * encoder, uint8_t * request, int length)
return 0;
}

uint8_t ctap_solo_kbd(CborEncoder * encoder, uint8_t * request, int length)
{
CTAP_soloKbd KBD;
int ret = ctap_parse_solo_kbd(&KBD, request, length);
if (ret != 0)
{
printf2(TAG_ERR,"error, ctap_parse_solo_kbd failed\n");
return ret;
}
dump_hex1(TAG_CTAP, KBD.sequence, KBD.length);
ctap_store_kbd(&KBD);
return 0;
}

uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
{
CTAP_getAssertion GA;
Expand Down Expand Up @@ -2318,6 +2332,10 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)

dump_hex1(TAG_DUMP,buf, resp->length);
break;
case CTAP_SOLO_KBD:
printf1(TAG_CTAP,"CTAP_SOLO_KBD\n");
status = ctap_solo_kbd(&encoder, pkt_raw, length);
break;
default:
status = CTAP1_ERR_INVALID_COMMAND;
printf2(TAG_ERR,"error, invalid cmd: 0x%02x\n", cmd);
Expand Down
6 changes: 6 additions & 0 deletions fido2/ctap.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define CTAP_CBOR_CRED_MGMT 0x0A
#define CTAP_VENDOR_FIRST 0x40
#define CTAP_CBOR_CRED_MGMT_PRE 0x41
#define CTAP_SOLO_KBD 0x51
#define CTAP_VENDOR_LAST 0xBF

#define MC_clientDataHash 0x01
Expand Down Expand Up @@ -338,6 +339,11 @@ typedef struct
int pinProtocol;
} CTAP_credMgmt;

typedef struct
{
uint8_t sequence[64];
uint8_t length;
} CTAP_soloKbd;

typedef struct
{
Expand Down
22 changes: 22 additions & 0 deletions fido2/ctap_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,28 @@ uint8_t ctap_parse_extensions(CborValue * val, CTAP_extensions * ext)
return 0;
}

uint8_t ctap_parse_solo_kbd(CTAP_soloKbd * KBD, uint8_t * request, int length)
{
int ret;
CborParser parser;
CborValue it;

memset(KBD, 0, sizeof(CTAP_soloKbd));
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
check_retr(ret);
CborType type = cbor_value_get_type(&it);
if (type != CborByteStringType)
{
printf2(TAG_ERR,"Error, expecting cbor byte string\n");
return CTAP2_ERR_CBOR_UNEXPECTED_TYPE;
}
size_t len = sizeof(KBD->sequence);
ret = cbor_value_copy_byte_string(&it, KBD->sequence, &len, NULL);
check_ret(ret);
KBD->length = len;
return ret;
}

uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length)
{
int ret;
Expand Down
1 change: 1 addition & 0 deletions fido2/ctap_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
uint8_t ctap_parse_cred_mgmt(CTAP_credMgmt * CM, uint8_t * request, int length);
uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length);
uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * cred);
uint8_t ctap_parse_solo_kbd(CTAP_soloKbd * KBD, uint8_t * request, int length);


#endif
3 changes: 2 additions & 1 deletion fido2/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ uint32_t millis();
*/
void usbhid_send(uint8_t * msg);


/** Reboot / power reset the device.
* **Optional** this is not used for FIDO2, and simply won't do anything if not implemented.
*/
Expand Down Expand Up @@ -163,6 +162,8 @@ void ctap_load_rk(int index,CTAP_residentKey * rk);
*/
void ctap_overwrite_rk(int index,CTAP_residentKey * rk);

void ctap_load_kbd(CTAP_soloKbd * kbd);
void ctap_store_kbd(CTAP_soloKbd * kbd);

/** Called by HID layer to indicate that a wink behavior should be performed.
* Should not block, and the wink behavior should occur in parallel to FIDO operations.
Expand Down
5 changes: 5 additions & 0 deletions pc/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,11 @@ void ctap_store_rk(int index, CTAP_residentKey * rk)

}

void ctap_store_kbd(CTAP_soloKbd * kbd)
{
// nop
}

void ctap_delete_rk(int index)
{
CTAP_residentKey rk;
Expand Down
4 changes: 2 additions & 2 deletions targets/stm32l432/build/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ DRIVER_LIBS := lib/stm32l4xx_hal_pcd.c lib/stm32l4xx_hal_pcd_ex.c lib/stm32l4xx_
USB_LIB := lib/usbd/usbd_cdc.c lib/usbd/usbd_cdc_if.c lib/usbd/usbd_composite.c \
lib/usbd/usbd_conf.c lib/usbd/usbd_core.c lib/usbd/usbd_ioreq.c \
lib/usbd/usbd_ctlreq.c lib/usbd/usbd_desc.c lib/usbd/usbd_hid.c \
lib/usbd/usbd_ccid.c
lib/usbd/usbd_ccid.c lib/usbd/usbd_kbd.c

VERSION_FULL?=$(SOLO_VERSION_FULL)
VERSION:=$(SOLO_VERSION)
Expand All @@ -32,4 +32,4 @@ _all:
echo $(SOLO_VERSION_PAT)

%.o: %.s
$(AS) -o $@ $^
$(AS) -o $@ $^
65 changes: 54 additions & 11 deletions targets/stm32l432/lib/usbd/usbd_composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);
#define CCID_SIZE 0
#endif

#ifdef ENABLE_KBD
#define KBD_SIZE 25
#define KBD_NUM_INTERFACE 1
#else
#define KBD_NUM_INTERFACE 0
#define KBD_SIZE 0
#endif

#if DEBUG_LEVEL > 0
#define CDC_SIZE (49 + 8 + 9 + 4)
#define CDC_NUM_INTERFACE 2
Expand All @@ -46,15 +54,16 @@ static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);

#define HID_SIZE 41

#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (HID_SIZE + CDC_SIZE + CCID_SIZE)
#define NUM_INTERFACES (1 + CDC_NUM_INTERFACE + CCID_NUM_INTERFACE)
#define NUM_CLASSES 3
#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (HID_SIZE + CDC_SIZE + CCID_SIZE + KBD_SIZE)
#define NUM_INTERFACES (1 + CDC_NUM_INTERFACE + CCID_NUM_INTERFACE + KBD_NUM_INTERFACE)
#define NUM_CLASSES 4


#define HID_INTF_NUM 0
#define CDC_MASTER_INTF_NUM 1
#define CDC_SLAVE_INTF_NUM 2
#define CCID_INTF_NUM 3
#define KBD_INTF_NUM 1
__ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_SIZE] __ALIGN_END =
{
/*Configuration Descriptor*/
Expand Down Expand Up @@ -284,7 +293,40 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_

#endif

#ifdef ENABLE_KBD
/* */
/* KBD */
/* */

/************** Descriptor of Keyboard interface ****************/
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE, /*bDescriptorType: Interface descriptor type*/
KBD_INTF_NUM, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x01, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
2, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Keyboard HID ********************/
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_KBD_REPORT_DESC_SIZE, /*wItemLength: Total length of Report descriptor*/
0,
/******************** Descriptor of Keyboard endpoint ********************/
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
KBD_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
KBD_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
KBD_BINTERVAL, /*bInterval: Polling Interval */
#endif
};

USBD_ClassTypeDef USBD_Composite =
Expand All @@ -311,7 +353,7 @@ int in_endpoint_to_class[MAX_ENDPOINTS];

int out_endpoint_to_class[MAX_ENDPOINTS];

void USBD_Composite_Set_Classes(USBD_ClassTypeDef *hid_class, USBD_ClassTypeDef *ccid_class, USBD_ClassTypeDef *cdc_class) {
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *hid_class, USBD_ClassTypeDef *ccid_class, USBD_ClassTypeDef *cdc_class, USBD_ClassTypeDef *kbd_class) {
memset(USBD_Classes, 0 , sizeof(USBD_Classes));
USBD_Classes[0] = hid_class;
#ifdef ENABLE_CCID
Expand All @@ -320,6 +362,9 @@ void USBD_Composite_Set_Classes(USBD_ClassTypeDef *hid_class, USBD_ClassTypeDef
#if DEBUG_LEVEL > 0
USBD_Classes[2] = cdc_class;
#endif
#ifdef ENABLE_KBD
USBD_Classes[1] = kbd_class;
#endif
}

static USBD_ClassTypeDef * getClass(uint8_t index)
Expand All @@ -336,6 +381,10 @@ static USBD_ClassTypeDef * getClass(uint8_t index)
case CDC_MASTER_INTF_NUM:
case CDC_SLAVE_INTF_NUM:
return USBD_Classes[2];
#endif
#ifdef ENABLE_KBD
case KBD_INTF_NUM:
return USBD_Classes[1];
#endif
}
return NULL;
Expand Down Expand Up @@ -364,7 +413,6 @@ static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
}

static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) {
int i;
USBD_ClassTypeDef * device_class;
device_class = getClass(req->wIndex);

Expand All @@ -380,12 +428,7 @@ static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqType
switch (req->bRequest) {

case USB_REQ_GET_DESCRIPTOR :
for(i = 0; i < NUM_CLASSES; i++) {
if (USBD_Classes[i] != NULL && USBD_Classes[i]->Setup(pdev, req) != USBD_OK) {
return USBD_FAIL;
}
}

return device_class->Setup(pdev, req);
break;

case USB_REQ_GET_INTERFACE :
Expand Down
2 changes: 1 addition & 1 deletion targets/stm32l432/lib/usbd/usbd_composite.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extern int in_endpoint_to_class[MAX_ENDPOINTS];

extern int out_endpoint_to_class[MAX_ENDPOINTS];

void USBD_Composite_Set_Classes(USBD_ClassTypeDef *class0, USBD_ClassTypeDef *class1, USBD_ClassTypeDef *class2);
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *class0, USBD_ClassTypeDef *class1, USBD_ClassTypeDef *class2, USBD_ClassTypeDef *class3);

#ifdef __cplusplus
}
Expand Down
2 changes: 2 additions & 0 deletions targets/stm32l432/lib/usbd/usbd_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, 0xd8 + 64*5); // data OUT
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, 0xd8 + 64*6); // data IN

// KBD
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , KBD_EPIN_ADDR , PCD_SNG_BUF, 0xd8 + 64*7); // data IN
// dump_pma_header("usbd_conf");

return USBD_OK;
Expand Down
8 changes: 8 additions & 0 deletions targets/stm32l432/lib/usbd/usbd_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,19 @@
#define HID_EPOUT_ADDR 0x01U
#define HID_EPOUT_SIZE HID_PACKET_SIZE

#define KBD_PACKET_SIZE 8
#define KBD_EPIN_ADDR 0x82U
#define KBD_EPIN_SIZE KBD_PACKET_SIZE

#define USB_HID_DESC_SIZ 9U
#define HID_FIDO_REPORT_DESC_SIZE 34U
#define HID_KBD_REPORT_DESC_SIZE 63U

#define HID_DESCRIPTOR_TYPE 0x21U
#define HID_REPORT_DESC 0x22U

#define HID_BINTERVAL 5
#define KBD_BINTERVAL 10

#define HID_REQ_SET_PROTOCOL 0x0BU
#define HID_REQ_GET_PROTOCOL 0x03U
Expand Down Expand Up @@ -94,9 +100,11 @@ typedef struct
USBD_HID_HandleTypeDef;

extern USBD_ClassTypeDef USBD_HID;
extern USBD_ClassTypeDef USBD_KBD;


void usb_hid_recieve_callback(uint8_t ep);
void usb_kbd_send(uint8_t *msg, int len);


#ifdef __cplusplus
Expand Down
Loading