Fixed u2f reentry
This commit is contained in:
parent
eb2ef2464c
commit
2ab950555e
159
firmware/u2f.c
159
firmware/u2f.c
|
@ -47,7 +47,7 @@
|
||||||
#define U2F_OUT_PKT_BUFFER_LEN 16
|
#define U2F_OUT_PKT_BUFFER_LEN 16
|
||||||
|
|
||||||
// Initialise without a cid
|
// Initialise without a cid
|
||||||
static uint32_t cid = CID_BROADCAST;
|
static uint32_t cid = 0;
|
||||||
|
|
||||||
// Circular Output buffer
|
// Circular Output buffer
|
||||||
static uint32_t u2f_out_start = 0;
|
static uint32_t u2f_out_start = 0;
|
||||||
|
@ -154,74 +154,131 @@ uint32_t next_cid(void)
|
||||||
return cid;
|
return cid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void u2fhid_read(const U2FHID_FRAME *f)
|
typedef struct {
|
||||||
{
|
uint8_t buf[57+127*59];
|
||||||
static uint8_t seq, cmd;
|
uint8_t *buf_ptr;
|
||||||
static uint32_t len;
|
uint32_t len;
|
||||||
static uint8_t *buf_ptr;
|
uint8_t seq;
|
||||||
static uint8_t buf[57+7*59];
|
uint8_t cmd;
|
||||||
|
} U2F_ReadBuffer;
|
||||||
|
|
||||||
if ((f->cid != CID_BROADCAST) && (f->cid != cid)) {
|
U2F_ReadBuffer *reader;
|
||||||
return; // Not for us
|
|
||||||
|
void u2fhid_read(char tiny, const U2FHID_FRAME *f)
|
||||||
|
{
|
||||||
|
if (tiny) {
|
||||||
|
// read continue packet
|
||||||
|
if (reader == 0 || cid != f->cid) {
|
||||||
|
send_u2fhid_error(f->cid, ERR_CHANNEL_BUSY);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->type & TYPE_INIT) {
|
if ((f->type & TYPE_INIT) || reader->seq != f->cont.seq) {
|
||||||
seq = 0;
|
u2fhid_init_cmd(f);
|
||||||
buf_ptr = buf;
|
return;
|
||||||
len = MSG_LEN(*f);
|
}
|
||||||
cmd = f->type;
|
|
||||||
memcpy(buf_ptr, f->init.data, sizeof(f->init.data));
|
// check out of bounds
|
||||||
buf_ptr += sizeof(f->init.data);
|
if ((reader->buf_ptr - reader->buf) >= (signed) reader->len
|
||||||
|
|| (reader->buf_ptr + sizeof(f->cont.data) - reader->buf) > (signed) sizeof(reader->buf))
|
||||||
|
return;
|
||||||
|
reader->seq++;
|
||||||
|
memcpy(reader->buf_ptr, f->cont.data, sizeof(f->cont.data));
|
||||||
|
reader->buf_ptr += sizeof(f->cont.data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u2fhid_read_start(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void u2fhid_init_cmd(const U2FHID_FRAME *f) {
|
||||||
|
reader->seq = 0;
|
||||||
|
reader->buf_ptr = reader->buf;
|
||||||
|
reader->len = MSG_LEN(*f);
|
||||||
|
reader->cmd = f->type;
|
||||||
|
memcpy(reader->buf_ptr, f->init.data, sizeof(f->init.data));
|
||||||
|
reader->buf_ptr += sizeof(f->init.data);
|
||||||
|
cid = f->cid;
|
||||||
|
// Check length isnt bigger than spec max
|
||||||
|
if (reader->len > sizeof(reader->buf)) {
|
||||||
|
reader->len = 0;
|
||||||
|
return send_u2fhid_error(cid, ERR_INVALID_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void u2fhid_read_start(const U2FHID_FRAME *f) {
|
||||||
|
U2F_ReadBuffer readbuffer;
|
||||||
|
if (!(f->type & TYPE_INIT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader = &readbuffer;
|
||||||
|
u2fhid_init_cmd(f);
|
||||||
|
|
||||||
// Broadcast is reserved for init
|
// Broadcast is reserved for init
|
||||||
if (f->cid == CID_BROADCAST && cmd != U2FHID_INIT)
|
if (f->cid == CID_BROADCAST && reader->cmd != U2FHID_INIT)
|
||||||
return;
|
return;
|
||||||
cid = f->cid;
|
|
||||||
|
|
||||||
// Check length isnt bigger than spec max
|
|
||||||
if (len > sizeof(buf)) {
|
|
||||||
len = 0;
|
|
||||||
return send_u2fhid_error(ERR_INVALID_LEN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// check out of bounds
|
|
||||||
if ((buf_ptr - buf) >= (signed) len
|
|
||||||
|| (buf_ptr + sizeof(f->cont.data) - buf) > (signed) sizeof(buf))
|
|
||||||
return;
|
|
||||||
if (f->cont.seq == seq) {
|
|
||||||
seq++;
|
|
||||||
memcpy(buf_ptr, f->cont.data, sizeof(f->cont.data));
|
|
||||||
buf_ptr += sizeof(f->cont.data);
|
|
||||||
} else {
|
|
||||||
return send_u2fhid_error(ERR_INVALID_SEQ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
usbTiny(1);
|
||||||
|
for(;;) {
|
||||||
// Do we need to wait for more data
|
// Do we need to wait for more data
|
||||||
if ((buf_ptr - buf) < (signed)len) {
|
while ((reader->buf_ptr - reader->buf) < (signed)reader->len) {
|
||||||
// debugLog(0, "", "u2fhid_read wait");
|
uint8_t lastseq = reader->seq;
|
||||||
|
uint8_t lastcmd = reader->cmd;
|
||||||
|
int counter = U2F_TIMEOUT;
|
||||||
|
while (reader->seq == lastseq && reader->cmd == lastcmd) {
|
||||||
|
if (counter-- == 0) {
|
||||||
|
// timeout
|
||||||
|
cid = 0;
|
||||||
|
send_u2fhid_error(f->cid, ERR_MSG_TIMEOUT);
|
||||||
|
usbTiny(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
usbPoll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We have all the data
|
// We have all the data
|
||||||
switch (cmd) {
|
switch (reader->cmd) {
|
||||||
case U2FHID_PING:
|
case U2FHID_PING:
|
||||||
u2fhid_ping(buf, len);
|
u2fhid_ping(reader->buf, reader->len);
|
||||||
break;
|
break;
|
||||||
case U2FHID_MSG:
|
case U2FHID_MSG:
|
||||||
u2fhid_msg((APDU *)buf, len);
|
u2fhid_msg((APDU *)reader->buf, reader->len);
|
||||||
break;
|
break;
|
||||||
case U2FHID_INIT:
|
case U2FHID_INIT:
|
||||||
u2fhid_init((const U2FHID_INIT_REQ *)buf);
|
u2fhid_init((const U2FHID_INIT_REQ *)reader->buf);
|
||||||
break;
|
break;
|
||||||
case U2FHID_WINK:
|
case U2FHID_WINK:
|
||||||
u2fhid_wink(buf, len);
|
u2fhid_wink(reader->buf, reader->len);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
send_u2fhid_error(ERR_INVALID_CMD);
|
send_u2fhid_error(cid, ERR_INVALID_CMD);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait for next commmand/ button press
|
||||||
|
reader->cmd = 0;
|
||||||
|
uint8_t bs = 0;
|
||||||
|
while (dialog_timeout-- && bs == 0 && reader->cmd == 0) {
|
||||||
|
usbPoll(); // may trigger new request
|
||||||
|
bs = buttonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader->cmd == 0) {
|
||||||
|
if (dialog_timeout == 0) {
|
||||||
|
last_req_state += BTN_NO; // Timeout is like button no
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last_req_state += bs;
|
||||||
|
dialog_timeout = 0;
|
||||||
|
}
|
||||||
|
cid = 0;
|
||||||
|
usbTiny(0);
|
||||||
|
layoutHome();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void u2fhid_ping(const uint8_t *buf, uint32_t len)
|
void u2fhid_ping(const uint8_t *buf, uint32_t len)
|
||||||
|
@ -236,7 +293,7 @@ void u2fhid_wink(const uint8_t *buf, uint32_t len)
|
||||||
(void)buf;
|
(void)buf;
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
return send_u2fhid_error(ERR_INVALID_LEN);
|
return send_u2fhid_error(cid, ERR_INVALID_LEN);
|
||||||
|
|
||||||
if (dialog_timeout > 0)
|
if (dialog_timeout > 0)
|
||||||
dialog_timeout = U2F_TIMEOUT;
|
dialog_timeout = U2F_TIMEOUT;
|
||||||
|
@ -308,7 +365,7 @@ void u2fhid_msg(const APDU *a, uint32_t len)
|
||||||
// Very crude locking, incase another message comes in while we wait. This
|
// Very crude locking, incase another message comes in while we wait. This
|
||||||
// actually can probably be removed as no code inside calls usbPoll anymore
|
// actually can probably be removed as no code inside calls usbPoll anymore
|
||||||
if (lock)
|
if (lock)
|
||||||
return send_u2fhid_error(ERR_CHANNEL_BUSY);
|
return send_u2fhid_error(cid, ERR_CHANNEL_BUSY);
|
||||||
|
|
||||||
lock = true;
|
lock = true;
|
||||||
|
|
||||||
|
@ -329,7 +386,7 @@ void u2fhid_msg(const APDU *a, uint32_t len)
|
||||||
|
|
||||||
lock = false;
|
lock = false;
|
||||||
|
|
||||||
LayoutHomeAfterTimeout();
|
//LayoutHomeAfterTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data, const uint32_t len)
|
void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data, const uint32_t len)
|
||||||
|
@ -371,12 +428,12 @@ void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data, const uint32_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_u2fhid_error(uint8_t err)
|
void send_u2fhid_error(uint32_t fcid, uint8_t err)
|
||||||
{
|
{
|
||||||
U2FHID_FRAME f;
|
U2FHID_FRAME f;
|
||||||
|
|
||||||
bzero(&f, sizeof(f));
|
bzero(&f, sizeof(f));
|
||||||
f.cid = cid;
|
f.cid = fcid;
|
||||||
f.init.cmd = U2FHID_ERROR;
|
f.init.cmd = U2FHID_ERROR;
|
||||||
f.init.bcntl = 1;
|
f.init.bcntl = 1;
|
||||||
f.init.data[0] = err;
|
f.init.data[0] = err;
|
||||||
|
|
|
@ -35,7 +35,9 @@ typedef struct {
|
||||||
|
|
||||||
#define APDU_LEN(A) (uint32_t)(((A).lc1 << 16) + ((A).lc2 << 8) + ((A).lc3))
|
#define APDU_LEN(A) (uint32_t)(((A).lc1 << 16) + ((A).lc2 << 8) + ((A).lc3))
|
||||||
|
|
||||||
void u2fhid_read(const U2FHID_FRAME *buf);
|
void u2fhid_read(char tiny, const U2FHID_FRAME *buf);
|
||||||
|
void u2fhid_init_cmd(const U2FHID_FRAME *f);
|
||||||
|
void u2fhid_read_start(const U2FHID_FRAME *f);
|
||||||
bool u2fhid_write(uint8_t *buf);
|
bool u2fhid_write(uint8_t *buf);
|
||||||
void u2fhid_init(const U2FHID_INIT_REQ *init_req);
|
void u2fhid_init(const U2FHID_INIT_REQ *init_req);
|
||||||
void u2fhid_ping(const uint8_t *buf, uint32_t len);
|
void u2fhid_ping(const uint8_t *buf, uint32_t len);
|
||||||
|
@ -50,11 +52,11 @@ void u2f_register(const APDU *a);
|
||||||
void u2f_version(const APDU *a);
|
void u2f_version(const APDU *a);
|
||||||
void u2f_authenticate(const APDU *a);
|
void u2f_authenticate(const APDU *a);
|
||||||
|
|
||||||
void send_u2f_msg(const uint8_t *data, const uint32_t len);
|
void send_u2f_msg(const uint8_t *data, uint32_t len);
|
||||||
void send_u2f_error(const uint16_t err);
|
void send_u2f_error(uint16_t err);
|
||||||
|
|
||||||
void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data,
|
void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data,
|
||||||
const uint32_t len);
|
const uint32_t len);
|
||||||
void send_u2fhid_error(const uint8_t err);
|
void send_u2fhid_error(uint32_t fcid, uint8_t err);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -230,14 +230,14 @@ static const struct usb_interface_descriptor hid_iface_debug[] = {{
|
||||||
static const struct usb_interface ifaces[] = {{
|
static const struct usb_interface ifaces[] = {{
|
||||||
.num_altsetting = 1,
|
.num_altsetting = 1,
|
||||||
.altsetting = hid_iface,
|
.altsetting = hid_iface,
|
||||||
}, {
|
|
||||||
.num_altsetting = 1,
|
|
||||||
.altsetting = hid_iface_u2f,
|
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
}, {
|
}, {
|
||||||
.num_altsetting = 1,
|
.num_altsetting = 1,
|
||||||
.altsetting = hid_iface_debug,
|
.altsetting = hid_iface_debug,
|
||||||
#endif
|
#endif
|
||||||
|
}, {
|
||||||
|
.num_altsetting = 1,
|
||||||
|
.altsetting = hid_iface_u2f,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const struct usb_config_descriptor config = {
|
static const struct usb_config_descriptor config = {
|
||||||
|
@ -308,7 +308,7 @@ static void hid_u2f_rx_callback(usbd_device *dev, uint8_t ep)
|
||||||
|
|
||||||
debugLog(0, "", "hid_u2f_rx_callback");
|
debugLog(0, "", "hid_u2f_rx_callback");
|
||||||
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_U2F_OUT, buf, 64) != 64) return;
|
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_U2F_OUT, buf, 64) != 64) return;
|
||||||
u2fhid_read((const U2FHID_FRAME *)buf);
|
u2fhid_read(tiny, (const U2FHID_FRAME *)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
|
|
Loading…
Reference in New Issue