Skip to content

Commit

Permalink
prevent overrun in CTAP-HID
Browse files Browse the repository at this point in the history
  • Loading branch information
z4yx committed Oct 18, 2023
1 parent 3ccbb6b commit 68e478e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
34 changes: 21 additions & 13 deletions interfaces/USB/class/ctaphid/ctaphid.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ uint8_t CTAPHID_Init(uint8_t (*send_report)(USBD_HandleTypeDef *pdev, uint8_t *r
}

uint8_t CTAPHID_OutEvent(uint8_t *data) {
if (has_frame) {
ERR_MSG("overrun\n");
return 0;
}
memcpy(&frame, data, sizeof(frame));
has_frame = 1;
return 0;
Expand Down Expand Up @@ -60,6 +64,7 @@ static void CTAPHID_SendResponse(uint32_t cid, uint8_t cmd, uint8_t *data, uint1
}

static void CTAPHID_SendErrorResponse(uint32_t cid, uint8_t code) {
DBG_MSG("error code 0x%x\n", (int)code);
memset(&frame, 0, sizeof(frame));
frame.cid = cid;
frame.init.cmd = CTAPHID_ERROR;
Expand Down Expand Up @@ -117,39 +122,39 @@ static void CTAPHID_Execute_Cbor(void) {
}

uint8_t CTAPHID_Loop(uint8_t wait_for_user) {
uint8_t ret = LOOP_SUCCESS;
if (channel.state == CTAPHID_BUSY && device_get_tick() > channel.expire) {
DBG_MSG("CTAP Timeout");
DBG_MSG("CTAP Timeout\n");
channel.state = CTAPHID_IDLE;
CTAPHID_SendErrorResponse(channel.cid, ERR_MSG_TIMEOUT);
return LOOP_SUCCESS;
}

if (!has_frame) return LOOP_SUCCESS;
has_frame = 0;

if (frame.cid == 0 || (frame.cid == CID_BROADCAST && frame.init.cmd != CTAPHID_INIT)) {
CTAPHID_SendErrorResponse(frame.cid, ERR_INVALID_CID);
return LOOP_SUCCESS;
goto consume_frame;
}
if (channel.state == CTAPHID_BUSY && frame.cid != channel.cid) {
CTAPHID_SendErrorResponse(frame.cid, ERR_CHANNEL_BUSY);
return LOOP_SUCCESS;
goto consume_frame;
}

channel.cid = frame.cid;

if (FRAME_TYPE(frame) == TYPE_INIT) {
// DBG_MSG("CTAP init frame, cmd=0x%x\n", (int)frame.init.cmd);
if (!wait_for_user && channel.state == CTAPHID_BUSY && frame.init.cmd != CTAPHID_INIT) { // self abort is ok
DBG_MSG("wait_for_user=%d, cmd=0x%x\n", (int)wait_for_user, (int)frame.init.cmd);
channel.state = CTAPHID_IDLE;
CTAPHID_SendErrorResponse(channel.cid, ERR_INVALID_SEQ);
return LOOP_SUCCESS;
goto consume_frame;
}
channel.bcnt_total = (uint16_t)MSG_LEN(frame);
if (channel.bcnt_total > MAX_CTAP_BUFSIZE) {
DBG_MSG("bcnt_total=%hu exceeds MAX_CTAP_BUFSIZE\n", channel.bcnt_total);
CTAPHID_SendErrorResponse(frame.cid, ERR_INVALID_LEN);
return LOOP_SUCCESS;
goto consume_frame;
}
uint16_t copied;
channel.bcnt_current = copied = MIN(channel.bcnt_total, ISIZE);
Expand All @@ -158,21 +163,22 @@ uint8_t CTAPHID_Loop(uint8_t wait_for_user) {
channel.seq = 0;
memcpy(channel.data, frame.init.data, copied);
channel.expire = device_get_tick() + CTAPHID_TRANS_TIMEOUT;
} else if (FRAME_TYPE(frame) == TYPE_CONT) {
} else {
// DBG_MSG("CTAP cont frame, state=%d cmd=0x%x seq=%d\n", (int)channel.state, (int)channel.cmd, (int)FRAME_SEQ(frame));
if (channel.state == CTAPHID_IDLE) return LOOP_SUCCESS; // ignore spurious continuation packet
if (channel.state == CTAPHID_IDLE) goto consume_frame; // ignore spurious continuation packet
if (FRAME_SEQ(frame) != channel.seq++) {
DBG_MSG("seq=%d\n", (int)FRAME_SEQ(frame));
channel.state = CTAPHID_IDLE;
CTAPHID_SendErrorResponse(channel.cid, ERR_INVALID_SEQ);
return LOOP_SUCCESS;
goto consume_frame;
}
uint16_t copied;
copied = MIN(channel.bcnt_total - channel.bcnt_current, CSIZE);
memcpy(channel.data + channel.bcnt_current, frame.cont.data, copied);
channel.bcnt_current += copied;
}
has_frame = 0;

uint8_t ret = LOOP_SUCCESS;
if (channel.bcnt_current == channel.bcnt_total) {
channel.expire = UINT32_MAX;
switch (channel.cmd) {
Expand Down Expand Up @@ -218,13 +224,15 @@ uint8_t CTAPHID_Loop(uint8_t wait_for_user) {
ret = LOOP_CANCEL;
break;
default:
DBG_MSG("Invalid CMD 0x%hhx\n", channel.cmd);
DBG_MSG("Invalid CMD 0x%x\n", (int)channel.cmd);
CTAPHID_SendErrorResponse(channel.cid, ERR_INVALID_CMD);
break;
}
channel.state = CTAPHID_IDLE;
}

consume_frame:
has_frame = 0;
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion src/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ uint8_t wait_for_user_presence(uint8_t entry) {
wait_status = shallow;
return USER_PRESENCE_TIMEOUT;
}
if (now - last >= 300) {
if (now - last >= 100) {
last = now;
if (wait_status != WAIT_CCID) CTAPHID_SendKeepAlive(KEEPALIVE_STATUS_UPNEEDED);
}
Expand Down

0 comments on commit 68e478e

Please sign in to comment.