mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-15 09:50:57 +00:00
core/webauthn: Fix CTAP HID protocol to correctly handle invalid channel IDs and interleaving packets from different channels.
This commit is contained in:
parent
9ea8136545
commit
0495d18b1e
@ -363,7 +363,7 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
|
|||||||
read = loop.wait(iface.iface_num() | io.POLL_READ)
|
read = loop.wait(iface.iface_num() | io.POLL_READ)
|
||||||
|
|
||||||
buf = await read
|
buf = await read
|
||||||
|
while True:
|
||||||
ifrm = overlay_struct(buf, desc_init)
|
ifrm = overlay_struct(buf, desc_init)
|
||||||
bcnt = ifrm.bcnt
|
bcnt = ifrm.bcnt
|
||||||
data = ifrm.data
|
data = ifrm.data
|
||||||
@ -376,6 +376,11 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
|
|||||||
log.warning(__name__, "_TYPE_CONT")
|
log.warning(__name__, "_TYPE_CONT")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if ifrm.cid == 0 or ((ifrm.cid == _CID_BROADCAST) and (ifrm.cmd != _CMD_INIT)):
|
||||||
|
# CID 0 is reserved for future use and _CID_BROADCAST is reserved for channel allocation
|
||||||
|
await send_cmd(cmd_error(ifrm.cid, _ERR_INVALID_CID), iface)
|
||||||
|
return None
|
||||||
|
|
||||||
if bcnt > _MAX_U2FHID_MSG_PAYLOAD_LEN:
|
if bcnt > _MAX_U2FHID_MSG_PAYLOAD_LEN:
|
||||||
# invalid payload length, abort current msg
|
# invalid payload length, abort current msg
|
||||||
if __debug__:
|
if __debug__:
|
||||||
@ -397,12 +402,10 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
|
|||||||
|
|
||||||
if cfrm.seq == _CMD_INIT:
|
if cfrm.seq == _CMD_INIT:
|
||||||
# _CMD_INIT frame, cancels current channel
|
# _CMD_INIT frame, cancels current channel
|
||||||
ifrm = overlay_struct(buf, desc_init)
|
|
||||||
data = ifrm.data[: ifrm.bcnt]
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if cfrm.cid != ifrm.cid:
|
if cfrm.cid != ifrm.cid:
|
||||||
# cont frame for a different channel, reply with BUSY and skip
|
# cont frame for a different channel, reply with BUSY and abort
|
||||||
if __debug__:
|
if __debug__:
|
||||||
log.warning(__name__, "_ERR_CHANNEL_BUSY")
|
log.warning(__name__, "_ERR_CHANNEL_BUSY")
|
||||||
await send_cmd(cmd_error(cfrm.cid, _ERR_CHANNEL_BUSY), iface)
|
await send_cmd(cmd_error(cfrm.cid, _ERR_CHANNEL_BUSY), iface)
|
||||||
@ -418,7 +421,7 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
|
|||||||
|
|
||||||
datalen += utils.memcpy(data, datalen, cfrm.data, 0, bcnt - datalen)
|
datalen += utils.memcpy(data, datalen, cfrm.data, 0, bcnt - datalen)
|
||||||
seq += 1
|
seq += 1
|
||||||
|
else:
|
||||||
return Cmd(ifrm.cid, ifrm.cmd, data)
|
return Cmd(ifrm.cid, ifrm.cmd, data)
|
||||||
|
|
||||||
|
|
||||||
@ -1051,9 +1054,7 @@ def dispatch_cmd(req: Cmd, dialog_mgr: DialogManager) -> Optional[Cmd]:
|
|||||||
|
|
||||||
|
|
||||||
def cmd_init(req: Cmd) -> Cmd:
|
def cmd_init(req: Cmd) -> Cmd:
|
||||||
if req.cid == 0:
|
if req.cid == _CID_BROADCAST:
|
||||||
return cmd_error(req.cid, _ERR_INVALID_CID)
|
|
||||||
elif req.cid == _CID_BROADCAST:
|
|
||||||
# uint32_t except 0 and 0xffffffff
|
# uint32_t except 0 and 0xffffffff
|
||||||
resp_cid = random.uniform(0xFFFFFFFE) + 1
|
resp_cid = random.uniform(0xFFFFFFFE) + 1
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user