From 3080007b125fcd62984d0154d454ffdca18d3349 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 2 May 2018 22:52:41 -0400 Subject: [PATCH] start ctap protocol --- Makefile | 3 ++ ctap.c | 84 +++++++++++++++++++++++++++++ ctap.h | 33 ++++++++++++ ctap_device.c | 56 ++++++++++++++++++++ ctaphid.c | 143 ++++++++++++++++++-------------------------------- ctaphid.h | 41 +-------------- main.c | 14 +---- 7 files changed, 231 insertions(+), 143 deletions(-) create mode 100644 ctap.c create mode 100644 ctap.h create mode 100644 ctap_device.c diff --git a/Makefile b/Makefile index 26a8cfb..2d16c00 100644 --- a/Makefile +++ b/Makefile @@ -8,3 +8,6 @@ name = main $(name): $(obj) $(CC) $(LDFLAGS) -o $@ $(obj) $(LDFLAGS) + +clean: + rm -f *.o main.exe main diff --git a/ctap.c b/ctap.c new file mode 100644 index 0000000..0335f4b --- /dev/null +++ b/ctap.c @@ -0,0 +1,84 @@ +#include +#include +#include + +#include "cbor.h" + +#include "ctap.h" +#include "util.h" + + + +static void check_ret(CborError ret) +{ + if (ret != CborNoError) + { + printf("CborError: %d: %s\n", ret, cbor_error_string(ret)); + exit(1); + } +} + + +void ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) +{ + uint8_t cmd = *pkt_raw; + int ret; + pkt_raw++; + + + uint8_t buf[100]; + memset(buf,0,sizeof(buf)); + + resp->data = buf; + resp->length = 0; + + CborEncoder encoder; + CborEncoder array; + + switch(cmd) + { + case CTAP_MAKE_CREDENTIAL: + printf("CTAP_MAKE_CREDENTIAL\n"); + break; + case CTAP_GET_ASSERTION: + printf("CTAP_GET_ASSERTION\n"); + break; + case CTAP_CANCEL: + printf("CTAP_CANCEL\n"); + break; + case CTAP_GET_INFO: + printf("CTAP_GET_INFO\n"); + + cbor_encoder_init(&encoder, buf, sizeof(buf), 0); + + ret = cbor_encoder_create_array(&encoder, &array, 2); + check_ret(ret); + + ret = cbor_encode_text_stringz(&array, "1.0"); + check_ret(ret); + ret = cbor_encode_text_stringz(&array, "2.0"); + check_ret(ret); + + ret = cbor_encoder_close_container(&encoder, &array); + check_ret(ret); + + dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf)); + + resp->length = cbor_encoder_get_buffer_size(&encoder, buf); + + break; + case CTAP_CLIENT_PIN: + printf("CTAP_CLIENT_PIN\n"); + break; + case CTAP_RESET: + printf("CTAP_RESET\n"); + break; + case GET_NEXT_ASSERTION: + printf("CTAP_NEXT_ASSERTION\n"); + break; + default: + printf("error, invalid cmd\n"); + } + + printf("cbor structure: %d bytes\n", length - 1); +} diff --git a/ctap.h b/ctap.h new file mode 100644 index 0000000..0626233 --- /dev/null +++ b/ctap.h @@ -0,0 +1,33 @@ +#ifndef _CTAP_H +#define _CTAP_H + +#define CTAP_MAKE_CREDENTIAL 0x01 +#define CTAP_GET_ASSERTION 0x02 +#define CTAP_CANCEL 0x03 +#define CTAP_GET_INFO 0x04 +#define CTAP_CLIENT_PIN 0x06 +#define CTAP_RESET 0x07 +#define GET_NEXT_ASSERTION 0x08 +#define CTAP_VENDOR_FIRST 0x40 +#define CTAP_VENDOR_LAST 0xBF + +typedef struct +{ + uint8_t * data; + uint16_t length; +} CTAP_RESPONSE; + + +void ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp); + +// Must be implemented by application +// data is HID_MESSAGE_SIZE long in bytes +extern void ctap_write_block(uint8_t * data); + +// Buffer data and send in HID_MESSAGE_SIZE chunks +// if len == 0, FLUSH +// if len == -1, RESET +extern void ctap_write(void * _data, int len); + + +#endif diff --git a/ctap_device.c b/ctap_device.c new file mode 100644 index 0000000..4e7bf5e --- /dev/null +++ b/ctap_device.c @@ -0,0 +1,56 @@ +/* + * Device specific functionality defined here + */ + +#include +#include +#include + +#include "cbor.h" + +#include "util.h" +#include "usbhid.h" + + +void ctap_write_block(uint8_t * data) +{ + printf("<< "); dump_hex(data, 64); + usbhid_send(data); +} + +void ctap_write(void * _data, int len) +{ + static uint8_t buf[HID_MESSAGE_SIZE]; + static int offset = 0; + + uint8_t * data = (uint8_t *) _data; + + if (len == 0) + { + if (offset > 0) + { + memset(buf + offset, 0, HID_MESSAGE_SIZE - offset); + ctap_write_block(buf); + } + offset = 0; + return; + } + else if (len == -1) + { + memset(buf, 0, HID_MESSAGE_SIZE); + offset = 0; + } + + int i; + for (i = 0; i < len; i++) + { + buf[offset++] = data[i]; + if (offset == HID_MESSAGE_SIZE) + { + ctap_write_block(buf); + offset = 0; + } + } +} + + diff --git a/ctaphid.c b/ctaphid.c index 5c700fb..f090d5f 100644 --- a/ctaphid.c +++ b/ctaphid.c @@ -4,6 +4,7 @@ #include #include "ctaphid.h" +#include "ctap.h" #include "time.h" #include "util.h" @@ -36,8 +37,6 @@ static int ctap_packet_seq; static uint32_t _next_cid = 0; -static void ctaphid_write(void * _data, int len); - void ctaphid_init() { state = IDLE; @@ -46,7 +45,7 @@ void ctaphid_init() ctap_buffer_bcnt = 0; ctap_buffer_offset = 0; ctap_packet_seq = 0; - ctaphid_write(NULL, -1); + ctap_write(NULL, -1); } static uint32_t set_next_cid(uint32_t cid) @@ -155,69 +154,35 @@ static int buffer_len() return ctap_buffer_bcnt; } -// Buffer data and send in HID_MESSAGE_SIZE chunks -static void ctaphid_write(void * _data, int len) -{ - static uint8_t buf[HID_MESSAGE_SIZE]; - static int offset = 0; - - uint8_t * data = (uint8_t *) _data; - - if (len == 0) - { - if (offset > 0) - { - memset(buf + offset, 0, HID_MESSAGE_SIZE - offset); - ctaphid_write_block(buf); - } - return; - } - else if (len == -1) - { - memset(buf, 0, HID_MESSAGE_SIZE); - offset = 0; - } - - int i; - for (i = 0; i < len; i++) - { - buf[offset++] = data[i]; - if (offset == HID_MESSAGE_SIZE) - { - ctaphid_write_block(buf); - offset = 0; - } - } -} static void ctaphid_send_error(uint32_t cid, uint8_t error) { uint8_t buf[HID_MESSAGE_SIZE]; memset(buf,0,sizeof(buf)); - CTAPHID_ERROR_RESPONSE * resp = (CTAPHID_ERROR_RESPONSE *) buf; + CTAPHID_RESPONSE * resp = (CTAPHID_RESPONSE *) buf; resp->cid = cid; resp->cmd = CTAPHID_ERROR; resp->bcnth = 0; resp->bcntl = 1; - resp->error = error; - ctaphid_write_block(buf); + buf[sizeof(CTAPHID_RESPONSE)] = error; + ctap_write_block(buf); } -void ctaphid_handle_packet(uint8_t * pkt_raw, CTAPHID_STATUS * stat) +void ctaphid_handle_packet(uint8_t * pkt_raw) { CTAPHID_PACKET * pkt = (CTAPHID_PACKET *)(pkt_raw); printf("Recv packet\n"); - printf(" CID: %08x\n", pkt->cid); + printf(" CID: %08x active(%08x)\n", pkt->cid, active_cid); printf(" cmd: %02x\n", pkt->pkt.init.cmd); printf(" length: %d\n", ctaphid_packet_len(pkt)); int ret; static CTAPHID_INIT_RESPONSE init_resp; - static CTAPHID_PING_RESPONSE ping_resp; - static CTAPHID_WINK_RESPONSE wink_resp; + static CTAPHID_RESPONSE resp; + + CTAP_RESPONSE ctap_resp; - memset(stat, 0, sizeof(CTAPHID_STATUS)); start_over: @@ -299,7 +264,6 @@ start_over: { case BUFFERING: printf("BUFFERING\n"); - stat->status = NO_RESPONSE; active_cid_timestamp = millis(); break; @@ -336,22 +300,21 @@ start_over: init_resp.build_version = 0;//? init_resp.capabilities = CAPABILITY_WINK | CAPABILITY_CBOR; - ctaphid_write(&init_resp,sizeof(CTAPHID_INIT_RESPONSE)); - ctaphid_write(NULL,0); + ctap_write(&init_resp,sizeof(CTAPHID_INIT_RESPONSE)); + ctap_write(NULL,0); - stat->status = CTAPHID_RESPONSE; break; case CTAPHID_PING: - ping_resp.cid = active_cid; - ping_resp.cmd = CTAPHID_PING; - ping_resp.bcnth = (buffer_len() & 0xff00) >> 8; - ping_resp.bcntl = (buffer_len() & 0xff) >> 0; + resp.cid = active_cid; + resp.cmd = CTAPHID_PING; + resp.bcnth = (buffer_len() & 0xff00) >> 8; + resp.bcntl = (buffer_len() & 0xff) >> 0; - ctaphid_write(&ping_resp,sizeof(CTAPHID_PING_RESPONSE)); - ctaphid_write(ctap_buffer, buffer_len()); - ctaphid_write(NULL,0); + ctap_write(&resp,sizeof(CTAPHID_RESPONSE)); + ctap_write(ctap_buffer, buffer_len()); + ctap_write(NULL,0); printf("CTAPHID_PING\n"); break; @@ -366,16 +329,41 @@ start_over: return; } - wink_resp.cid = active_cid; - wink_resp.cmd = CTAPHID_WINK; - wink_resp.bcnt = 0; + resp.cid = active_cid; + resp.cmd = CTAPHID_WINK; + resp.bcntl = 0; + resp.bcnth = 0; - ctaphid_write(&wink_resp,sizeof(CTAPHID_WINK_RESPONSE)); - ctaphid_write(NULL,0); + ctap_write(&resp,sizeof(CTAPHID_RESPONSE)); + ctap_write(NULL,0); printf("CTAPHID_WINK\n"); break; + case CTAPHID_CBOR: + printf("CTAPHID_CBOR\n"); + if (buffer_len() == 0) + { + printf("Error,invalid 0 length field for cbor packet\n"); + ctaphid_send_error(pkt->cid, ERR_INVALID_LEN); + ctaphid_init(); + return; + } + + ctap_handle_packet(ctap_buffer, buffer_len(), &ctap_resp); + + resp.cid = active_cid; + resp.cmd = CTAPHID_MSG; + resp.bcntl = (ctap_resp.length & 0x00ff) >> 0; + resp.bcnth = (ctap_resp.length & 0xff00) >> 8; + + ctap_write(&resp,sizeof(CTAPHID_RESPONSE)); + ctap_write(ctap_resp.data, ctap_resp.length); + ctap_write(NULL, 0); + + + break; + default: printf("error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); break; @@ -387,37 +375,8 @@ start_over: exit(1); break; } - - -} - - -void ctaphid_dump_status(CTAPHID_STATUS * stat) -{ - switch(stat->status) - { - case NO_RESPONSE: - printf("NO_RESPONSE"); - break; - case CTAPHID_RESPONSE: - printf("CTAPHID_RESPONSE"); - break; - case U2F_RESPONSE: - printf("U2F_RESPONSE"); - break; - case CBOR_RESPONSE: - printf("CBOR_RESPONSE"); - break; - default: - printf("\ninvalid status %d; abort\n", stat->status); - exit(1); - } + printf("\n"); - /*printf(" (%d)\n ", stat->length);*/ - /*if (stat->length > 0)*/ - /*{*/ - /*dump_hex(stat->data, stat->length);*/ - /*}*/ + } - diff --git a/ctaphid.h b/ctaphid.h index dc09edf..e7c2561 100644 --- a/ctaphid.h +++ b/ctaphid.h @@ -74,54 +74,17 @@ typedef struct uint8_t cmd; uint8_t bcnth; uint8_t bcntl; -} __attribute__((packed)) CTAPHID_PING_RESPONSE; - - -typedef struct -{ - uint32_t cid; - uint8_t cmd; - uint16_t bcnt; -} __attribute__((packed)) CTAPHID_WINK_RESPONSE; - - -typedef struct -{ - uint32_t cid; - uint8_t cmd; - uint8_t bcnth; - uint8_t bcntl; - uint8_t error; -} __attribute__((packed)) CTAPHID_ERROR_RESPONSE; +} __attribute__((packed)) CTAPHID_RESPONSE; -// API specific, not protocol specific // -typedef enum -{ - NO_RESPONSE = 0, - CTAPHID_RESPONSE, - U2F_RESPONSE, - CBOR_RESPONSE, -} CTAPHID_CODE; - -typedef struct -{ - int status; -} CTAPHID_STATUS; -//////// - void ctaphid_init(); -void ctaphid_handle_packet(uint8_t * pkt_raw, CTAPHID_STATUS * stat); +void ctaphid_handle_packet(uint8_t * pkt_raw); -void ctaphid_dump_status(CTAPHID_STATUS * stat); -// Must be implemented by application -// data is HID_MESSAGE_SIZE long in bytes -extern void ctaphid_write_block(uint8_t * data); #define ctaphid_packet_len(pkt) ((uint16_t)((pkt)->pkt.init.bcnth << 8) | ((pkt)->pkt.init.bcntl)) diff --git a/main.c b/main.c index a1ffc5a..91ae7b6 100644 --- a/main.c +++ b/main.c @@ -8,7 +8,7 @@ #include "util.h" -void check_ret(CborError ret) +static void check_ret(CborError ret) { if (ret != CborNoError) { @@ -18,14 +18,6 @@ void check_ret(CborError ret) } -void ctaphid_write_block(uint8_t * data) -{ - printf("usbhid send\n"); - dump_hex(data, 64); - usbhid_send(data); -} - - int main(int argc, char * argv[]) { /*CborError ret;*/ @@ -45,7 +37,6 @@ int main(int argc, char * argv[]) int count = 0; uint8_t hidmsg[64]; - CTAPHID_STATUS res; memset(hidmsg,0,sizeof(hidmsg)); printf("recv'ing hid msg \n"); @@ -55,9 +46,8 @@ int main(int argc, char * argv[]) usbhid_recv(hidmsg); printf("%d>> ",count++); dump_hex(hidmsg,sizeof(hidmsg)); - ctaphid_handle_packet(hidmsg, &res); + ctaphid_handle_packet(hidmsg); memset(hidmsg, 0, sizeof(hidmsg)); - ctaphid_dump_status(&res); /*int i;*/ /*for(i = 0; i < res.length; i += 64)*/