diff --git a/ctaphid.c b/ctaphid.c new file mode 100644 index 0000000..0325cf1 --- /dev/null +++ b/ctaphid.c @@ -0,0 +1,109 @@ +#include +#include + +#include "ctaphid.h" +#include "time.h" + +typedef enum +{ + IDLE = 0, + HANDLING_REQUEST, +} CTAP_STATE; + +static int state; +static int active_cid; +static uint64_t active_cid_timestamp; +static uint8_t ctap_buffer[CTAPHID_BUFFER_SIZE]; + +void ctaphid_init() +{ + state = IDLE; + active_cid = 0; + active_cid_timestamp = millis(); +} + +uint32_t get_new_cid() +{ + static uint32_t cid = 1; + return cid++; +} + +static int is_broadcast(CTAPHID_PACKET * pkt) +{ + return (pkt->cid == CTAPHID_BROADCAST_CID); +} + +static int is_init_pkt(CTAPHID_PACKET * pkt) +{ + return (pkt->pkt.init.cmd == CTAPHID_INIT); +} + +static int is_active_cid(CTAPHID_PACKET * pkt) +{ + return (pkt->cid == active_cid); +} + +static int is_timed_out() +{ + return (millis() - active_cid_timestamp > 500); +} + + + +void ctaphid_handle_packet(uint8_t * pkt_raw) +{ +/*HID_MESSAGE_SIZE*/ + CTAPHID_PACKET * pkt = (CTAPHID_PACKET *)(pkt_raw); + + printf("Recv packet\n"); + printf(" CID: %08x\n", pkt->cid); + printf(" cmd: %02x\n", pkt->pkt.init.cmd); + printf(" length: %d\n", ctaphid_packet_len(pkt)); + +start_over: + + switch (state) + { + case IDLE: + if (is_broadcast(pkt)) + { + printf("starting a new request\n"); + state = HANDLING_REQUEST; + active_cid = get_new_cid(); + active_cid_timestamp = millis(); + } + else + { + printf("Error, unknown request\n"); + } + break; + case HANDLING_REQUEST: + if (is_active_cid(pkt)) + { + if (is_init_pkt(pkt)) + { + printf("received abort request from %08x\n", pkt->cid); + ctaphid_init(); + + } + active_cid_timestamp = millis(); + } + else if (is_timed_out()) + { + ctaphid_init(); + goto start_over; + } + else + { + printf("Too busy with current transaction\n"); + } + break; + default: + printf("invalid state\n"); + exit(1); + } + +} + + + diff --git a/ctaphid.h b/ctaphid.h new file mode 100644 index 0000000..8241172 --- /dev/null +++ b/ctaphid.h @@ -0,0 +1,47 @@ +#ifndef _CTAPHID_H_H +#define _CTAPHID_H_H + +#include "usbhid.h" + +#define TYPE_MASK 0x80 // Frame type mask +#define TYPE_INIT 0x80 // Initial frame identifier +#define TYPE_CONT 0x00 // Continuation frame identifier + +#define CTAPHID_PING (TYPE_INIT | 0x01) // Echo data through local processor only +#define CTAPHID_MSG (TYPE_INIT | 0x03) // Send U2F message frame +#define CTAPHID_LOCK (TYPE_INIT | 0x04) // Send lock channel command +#define CTAPHID_INIT (TYPE_INIT | 0x06) // Channel initialization +#define CTAPHID_WINK (TYPE_INIT | 0x08) // Send device identification wink +#define CTAPHID_ERROR (TYPE_INIT | 0x3f) // Error response + +#define CTAPHID_INIT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-7) +#define CTAPHID_CONT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-5) + +#define CTAPHID_BROADCAST_CID 0xffffffff + +#define CTAPHID_BUFFER_SIZE 4096 + +typedef struct +{ + uint32_t cid; + union{ + struct{ + uint8_t cmd; + uint8_t bcnth; + uint8_t bcntl; + uint8_t payload[CTAPHID_INIT_PAYLOAD_SIZE]; + } init; + struct{ + uint8_t seq; + uint8_t payload[CTAPHID_CONT_PAYLOAD_SIZE]; + } cont; + } pkt; +} CTAPHID_PACKET; + +void ctaphid_init(); + +void ctaphid_handle_packet(uint8_t * pkt_raw); + +#define ctaphid_packet_len(pkt) ((uint16_t)((pkt)->pkt.init.bcnth << 8) | ((pkt)->pkt.init.bcntl)) + +#endif diff --git a/main.c b/main.c index 58ccea1..5791755 100644 --- a/main.c +++ b/main.c @@ -4,6 +4,7 @@ #include "cbor.h" #include "usbhid.h" +#include "ctaphid.h" #include "util.h" @@ -18,18 +19,20 @@ void check_ret(CborError ret) int main(int argc, char * argv[]) { - CborError ret; - uint8_t buf[16]; - memset(buf,0,sizeof(buf)); - CborEncoder encoder; - cbor_encoder_init(&encoder, buf, sizeof(buf), 0); - ret = cbor_encode_int(&encoder, 55); - check_ret(ret); + /*CborError ret;*/ + /*uint8_t buf[16];*/ + /*memset(buf,0,sizeof(buf));*/ + /*CborEncoder encoder;*/ + /*cbor_encoder_init(&encoder, buf, sizeof(buf), 0);*/ + /*ret = cbor_encode_int(&encoder, 55);*/ + /*check_ret(ret);*/ - dump_hex(buf,sizeof(buf)); + /*dump_hex(buf,sizeof(buf));*/ printf("init usbhid\n"); usbhid_init(); + printf("init ctaphid\n"); + ctaphid_init(); uint8_t hidmsg[64]; memset(hidmsg,0,sizeof(hidmsg)); @@ -40,6 +43,8 @@ int main(int argc, char * argv[]) { usbhid_recv(hidmsg); printf(">> "); dump_hex(hidmsg,sizeof(hidmsg)); + + ctaphid_handle_packet(hidmsg); printf("<< "); dump_hex(hidmsg,sizeof(hidmsg)); usbhid_send(hidmsg); } diff --git a/time.c b/time.c new file mode 100644 index 0000000..a77e4bd --- /dev/null +++ b/time.c @@ -0,0 +1,10 @@ +#include +#include + +uint64_t millis() +{ + struct timeval te; + gettimeofday(&te, NULL); // get current time + uint64_t milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds + return milliseconds; +} diff --git a/time.h b/time.h new file mode 100644 index 0000000..41b45e4 --- /dev/null +++ b/time.h @@ -0,0 +1,6 @@ +#ifndef _TIME_H +#define _TIME_H + +uint64_t millis(); + +#endif